如何在数据框中对 csv 文件进行排序和连接

Posted

技术标签:

【中文标题】如何在数据框中对 csv 文件进行排序和连接【英文标题】:How can I sort and concat a csv file in a dataframe 【发布时间】:2022-01-15 21:48:57 【问题描述】:

我目前在一个项目中,我需要处理大量的 CSV 文件,这些文件充满了类似这样的数据:

    CSV1.csv

      A      B     C     D    ...
    1 1980  1     0.9   0.8
    2 2003  0.9   0.8   0.2
    3 1665  0.7   0.2   0.4
    4 1982  0.6   1     0.2
   ...

     CSV2.csv
      A      E     F     G   ...
    1 1665  1     0.4   1
    2 1980  0.4   0.8   0.6
    3 2003  0.1   0.3   0.9
    4 1982  0.3   1     0.6
   ...
  

所有 CSV 文件在 A 列中具有相同的值,但杂乱无章。我正在导入这样的所有文件:

path = r"/Users/.../folder/"
all_files = glob.glob(path + "/*.CSV")
all_csv = (pd.read_csv(f, sep=',') for f in all_files)
df_merged   = pd.concat(all_csv, axis=1, ignore_index=False) 

它被合并,但数据框杂乱无章。

使用df_merged.sort() 排序是不正确的,因为在A 处没有具有相同顺序的列。我知道我可以手动导入每个 csv 文件并应用 .sort(),但这些是 394 个 csv 文件...

我觉得 like this 可能适用于大量 CSV 文件的导入,但我不知道如何调用代码行之前数据框组合 (all_csv是一个生成器对象)。


附:最后我执行以消除重复的A 列:

df_merged = df_merged.loc[:, ~df_merged.columns.duplicated()]

【问题讨论】:

【参考方案1】:

您应该将每个数据帧合并在一起,而不是使用 concat:

df = all_csv[0]
for csv in all_csv[1:]:
    df = df.merge(csv)

输出:

>>> df
      A    B    C    D    E    F    G
0  1980  1.0  0.9  0.8  0.4  0.8  0.6
1  2003  0.9  0.8  0.2  0.1  0.3  0.9
2  1665  0.7  0.2  0.4  1.0  0.4  1.0
3  1982  0.6  1.0  0.2  0.3  1.0  0.6

注意:您需要将all_csv 设为列表而不是生成器:

all_csv = [pd.read_csv(f, sep=',') for f in all_files]

【讨论】:

感谢您的回答,我认为它有效。为了应用你所说的,我必须将 all_csv 从对象生成器转换为行,如下所示: all_csv = list(all_csv) 更好的方法是根本不创建生成器。像这样初始化all_csv 时使用方括号而不是括号:all_csv = [pd.read_csv(f, sep=',') for f in all_files]【参考方案2】:

    对齐可以通过设置A为索引来获得。

    使用数据帧列表并不吸引人,因为这会占用大量内存。

    解决方案 1: 在循环中构建其他数据框
    import pandas as pd
    
    path = r"/Users/.../folder/"
    all_files = glob.glob(path + "/*.CSV")
    
    df = pd.read_csv(all_files[0], sep=',').set_index('A')
    for f in all_files[1:]:
        dfs = pd.read_csv(f, sep=',').set_index('A')
        df = pd.concat([df, dfs], axis=1)
    
    解决方案2:保留生成器并使用functools.reduce
    import pandas as pd
    from functools import reduce
    
    path = r"/Users/.../folder/"
    all_files = glob.glob(path + "/*.CSV")
    
    def_gen = (pd.read_csv(io.StringIO(fn), sep='\s+').set_index('A') for fn in all_files)
    df = reduce(lambda df, d: pd.concat([df, d], axis=1), def_gen)
    

    df:

            B    C    D    E    F    G
    A                                 
    1665  0.7  0.2  0.4  1.0  0.4  1.0
    1980  1.0  0.9  0.8  0.4  0.8  0.6
    1982  0.6  1.0  0.2  0.3  1.0  0.6
    2003  0.9  0.8  0.2  0.1  0.3  0.9
    

就个人而言,我会采用简单的路径(“解决方案 1”)并添加一些日志记录来确定哪里会出现导入错误。因为在现实世界中,数据很少是干净且格式正确的。

【讨论】:

谢谢你,我喜欢你正在做的事情......但是在第一个选项中,如果 set_index('A') 第一列可能不总是相同的名称,我怎么能选择它? 顺便说一句,它工作得很好!非常感谢:) @Juank,要连接、加入、合并等,您至少需要一个密钥。要么键是显式的(有名称),要么至少键是隐式的(第一个“字段”)。您能否提供数据的子集(或模型),因为 CSV1.csv 和 CSV2.csv 似乎与您的数据不完全匹配(即它们有一个名为“A”的公共字段)并确认您要对齐在第一个字段上。 @Juank,是的,代码有效。但坦率地说,我会采取简单的路径(“解决方案 1”)并添加一些日志记录来确定哪里会出现导入错误。因为在现实世界中,数据很少干净且格式正确..

以上是关于如何在数据框中对 csv 文件进行排序和连接的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 中对大量字典进行排序而不加载到内存中

如何在熊猫数据框中对字符串进行排序或检查等效性而不考虑顺序?

如何在 Spark 中对包含日期和时间值的列进行排序?

如何连接两个csv文件然后按python排序

如何编写自定义函数以在 python 中对数据帧进行排序和透视

如何使用 row.names 属性在 R 中对数据框的行进行排序?