【问题标题】:Python Looping through txt files to create and merging Pandas DataframesPython 循环遍历 txt 文件以创建和合并 Pandas 数据框
【发布时间】:2015-09-10 20:17:15
【问题描述】:

在循环中创建并合并到现有 Dataframe 的最佳方法是什么?我有一个日志文件(比如 FILENAME1),它生成 txt 文件,提供我感兴趣的统计信息。我有一个脚本循环并打开每个 txt 文件并使用 pd.read_csv 生成一个 DataFrame。然后我使用 xlsxwriter 将每个 Dataframe 粘贴到 Excel。

我遇到的问题是每个 txt 文件都与下一个不同,当我对下一个文件 (FILENAME2) 执行相同操作时添加到此文件中,我实际上是从一张白纸开始。

例如eash日志文件会生成say:

FILENAME1
Tech_Summary.txt
Error_Totals.txt

然后我循环处理这些 txt 文件(DataFrame 它们)并粘贴到 Excel 并在完成后删除。然后下一个文件生成相同文件名的类似文件:

FILENAME2
Tech_Summary.txt
Error_Totals.txt

我的循环需要工作,因为我每次打开一个新的 txt 文件时都会覆盖 Dataframe,因为合并功能没有像我希望的那样工作。但我希望将每个迭代生成的数据帧与前一个迭代数据帧合并......但是基于每个 txt 文件

这是我目前的尝试

#Outline Dict items (make it generic for expansion)
TextExtractor={

    "Tech":{'txtfileID':'Tech_Summary',
                'lineskip':16,
                'linegrab':3,
                'linesplit':'% of Time in |;',
                'all_cols_labled':[1,'Tech','Percent','Null'],
                'cols_grab':['Tech','Percent'],
                'container':[],
                },      

        """ SAMPLE OF DF CREATED for "Tech"
           Tech    Percent Iter         Filename
        0  Type1        0  Iteration_1  Tech
        1  Type2      100  Iteration_1  Tech
        2  Type3        0  Iteration_1  Tech
        """

    "Errors":{'txtfileID':'Error_Totals',
                'lineskip':19,
                'linegrab':13,
                'linesplit':';',
                'all_cols_labled':['Scheme','Tot Errors','Tot Count','Percentage'],
                'cols_grab':['Scheme','Tot Errors','Tot Count','Percentage'],
                'container':[],
                },  

        """ SAMPLE OF DF CREATED for "Errors"
               Scheme  Tot Errors  Tot Count  Percentage    Iter        Filename
        0        -1        0           0     0              Iteration_1  Errors
        1        -2        0           0     0              Iteration_1  Errors
        2        -3        0           0     0              Iteration_1  Errors
        3        -4        0           0     0              Iteration_1  Errors
        4        -5       97           0     0              Iteration_1  Errors
        5        -6       55           0     0              Iteration_1  Errors
        """
}

looprun = 0
for textfile in os.listdir(resdir):
    if textfile.endswith('.txt'):
        for key in TextExtractor:
            #Set out rows and cols for Excel
            txtxlcol = XL_TextFileCoords['COLUMN']
            txtxlrow = XL_TextFileCoords['ROW']

            if TextExtractor[key]['txtfileID'] in textfile:
                #open each txt file and grab the selected data to make dataframe (DF)
                txt = pd.read_csv(resdir+'\\'+textfile, skiprows=TextExtractor[key]['lineskip'], nrows=TextExtractor[key]['linegrab'], header=None, sep=TextExtractor[key]['linesplit'], names=TextExtractor[key]['all_cols_labled'], usecols=TextExtractor[key]['cols_grab'], engine='python')
                #make dataframe
                txtDF = DataFrame(txt)
                #add iteration column to differentiate between each FILENAME
                txtDF['Iter'] = pd.Series(logID, index=txtDF.index)
                #add key column to DF to know what text file the data is from
                txtDF['Filename'] = pd.Series(key, index=txtDF.index)
                #convert DF to list ready to drop into each key (txt file) for later processing                 
                converttolist = txtDF.set_index(txtDF.index).T.to_dict('list')
                #Drop converted DF data into [key]['container'] for each txt file type based on key
                TextExtractor[key]['container'].append(converttolist)

                #write DF to Excel file
                txtDF.to_excel(writer, sheet_name=logID,startrow=txtxlrow, startcol=txtxlcol,index=False, header=False, columns=TextExtractor[key]['cols_grab'])
                #...do excel plotting stuff here

        #remove txt files from directory ready for next FILENAME (Iteration)
        os.remove(resdir+"/"+textfile)
    else:
        pass

for key in TextExtractor:
    print TextExtractor[key]['container']

所以目前我将 DataFrames 放入一个字典列表中,但我真的在寻找类似这种输出的东西。但保留上面的循环功能以供使用

""" 
# FINAL DATAFRAME 1
Type    Iter        Percent
Type1   Iteration_1  0
        Iteration_2  100
        Iteration_3  0
Type2   Iteration_1  40
        Iteration_2  30
        Iteration_3  30
Type3   Iteration_1  15
        Iteration_2  55
        Iteration_3  30 

# FINAL DATAFRAME 2 
Scheme  Iter        Tot Errors  Tot Count  Percentage
-1      Iteration_1  0          5           30
        Iteration_2  0          5           12
        Iteration_3  7          7           12
-2      Iteration_1  7          9           18
        Iteration_2  6          0           9
        Iteration_3  5          2           17
-3      Iteration_1  5          4           17
        Iteration_2  6          1           12
        Iteration_3  9          6           21
-4      Iteration_1  8          7           18
        Iteration_2  4          8           12
        Iteration_3  4          3           84
-5      Iteration_1  3          2           91
etc...

"""

任何建议将不胜感激。

【问题讨论】:

  • 你想在什么意义上“合并”数据框?您希望它们成为一个大型数据框的一部分吗?这就是合并的建议,但您显示的输出有单独的表格。
  • 嗨 ASGM,理想情况下我想根据 txt 文件名合并每个数据帧,所以如果两个 txt 文件是两个数据帧。但是,对于我的循环解决方案,我不确定这是可能的,并且可能不得不求助于一个大数据框。不幸的是,如果我想稍后添加更多 txt 文件,我会沿着循环路径使其更通用且易于扩展
  • 抱歉,我仍然很困惑 - 如果您在流程结束时仍需要两个单独的数据帧,那么“合并”数据帧是什么意思?两个文件,两个数据框——合并在哪里?
  • 嗨 ASGM。为混乱道歉。基本上我有一个文件夹,里面有几个日志。我有一个单独的脚本来解析每个日志,然后它会生成包含我想要获取的有用信息的 txt 文件。然后,我在示例代码中循环遍历每个 txt 文件(比如 Tech_Summary.txt 和 Error_Totals.txt)以生成数据框并在此过程中粘贴到 Excel。最后我会删除txt文件。我将移至目录中的下一个日志,再次解析为 txt 文件(再次为 Tech_Summary.txt 和 Error_Totals.txt),然后重复。所以在说 10 条日志结束时,我希望得到两个单独的 DF
  • 我应该提到我将日志解析为 txt,然后遍历 txt 文件以创建 DF,然后删除文本文件。然后转到目录中的下一个日志文件,将其解析为 txt,再次遍历新的(但名称相同的)txt 文件,删除它们等等。希望这是有道理的?

标签: python pandas


【解决方案1】:

简单的答案:将每个新的 DataFrame 放入字典中,以迭代为键。然后在最后合并它们。


我现在想我明白发生了什么。您有一系列日志:L1, L2 ... LN。从每个日志中提取两种文本文件,ab。所以你有L1a, L2a ... LNaL1b, L2b ... LNb。最后需要两个 DataFrame,dfadfb

我将首先提取将文本文件制作成 DataFrame 的代码,并将其制作成自己的函数。您无需添加 IterFilename 列,因为它们在 DataFrame 中是相同的,我们将在其他地方处理这些信息。

def df_from_txt(resdir, textfile, key):
    txt = pd.read_csv(
         resdir+'\\'+textfile, 
         skiprows=TextExtractor[key]['lineskip'], 
         nrows=TextExtractor[key]['linegrab'], 
         header=None, 
         sep=TextExtractor[key]['linesplit'], 
         names=TextExtractor[key]['all_cols_labled'],  
         usecols=TextExtractor[key]['cols_grab'], 
         engine='python')
     return DataFrame(txt)

现在提取逻辑与循环分离,更容易看到逻辑。您还需要添加一个容器字典来保存文本文件解析的结果。

dfs = {key: {} for key in TextExtractor.keys()}

for textfile in os.listdir(resdir):
    if textfile.endswith('.txt'):
        for key in TextExtractor:
            if TextExtractor[key]['txtfileID'] in textfile:
                df = df_from_txt(resdir, textfile, key)
                dfs[key][textfile] = df

现在您有了一个字典 (dfs),其键是您从日志中提取的不同类型的文本文件("Tech""Errors")。这些值本身就是字典,其中的键是文本文件的名称(如果 textfile 始终相同,则可以为键使用其他值 - logID 在您的原始函数中来自哪里?)。剩下的就是合并二级词典的内容了:

merged_dfs = {key: pd.concat(dfs[key]) for key in dfs.keys()}

现在您有了一个字典,其中键仍然是 "Tech""Errors",但值是单个 DataFrame。

如果这不起作用,可能是我误解了您的数据结构。如果您可以发布一个简单的工作示例,它会更容易提供帮助。

【讨论】:

  • 嗨,AGSM,很抱歉延迟回复,这两周我一直在度假。今天尝试了您的解决方案,看起来它正在按照我正在寻找的方式工作。感谢您的帮助和建议。
猜你喜欢
  • 2021-05-21
  • 1970-01-01
  • 2018-05-30
  • 2016-04-25
  • 2022-01-20
  • 2020-07-18
  • 1970-01-01
  • 2021-08-20
  • 2021-03-06
相关资源
最近更新 更多