【问题标题】:Combine similar CSV rows in python efficiently在 python 中有效地组合相似的 CSV 行
【发布时间】:2018-02-03 18:50:24
【问题描述】:

我想将一个非常大的 csv 文件(每个文件近 1GB!)中的相似行合并为一个。我有兴趣做这样的事情:

之前

First Name | Last Name | Phone Number | Email

John       | Doe       | 1234         | john@doe.com
Jane       | Doe       | 4321         | jane@doe.com
John       | Doe       | 6789         | john@gmail.com
Jane       | Doe       | 9876         | jane@gmail.com

之后

First Name | Last Name | Phone Number | Email

John       | Doe       | 1234, 6789   | john@doe.com, john@gmail.com
Jane       | Doe       | 4321, 9876   | jane@doe.com, jane@gmail.com

也就是说,使用名字和姓氏以及电话和电子邮件组合行,以将它们添加到“列表”中。

谢谢

【问题讨论】:

  • 如果你有一个标记为大数据的问题,你可能不应该使用 itertools。
  • 我应该使用什么?
  • @TripleNipple 1 GB 肯定是一个大文件,但我会为您的问题删除 bigdata 标记,因为您的用例可以在单台机器上处理 1 GB 文件。
  • 熊猫解决方案对您有用吗?
  • 嗯,你真的可以把整个东西保存在内存中,作为一个列表列表吗?因为那时你可以对其进行排序,然后是itertools.groupby。或者,也许考虑pandas

标签: python pandas csv dataframe


【解决方案1】:

要读入您的 CSV 文件,您需要 pd.read_csv:

 df = pd.read_csv('file.csv', delimiter='|', sep='\s+')

您将致电 df.groupby First NameLast Name 然后 dfGroupBy.agg 加入:

print(df)

    First Name    Last Name  Phone Number            Email
0  John          Doe                 1234     john@doe.com
1  Jane          Doe                 4321     jane@doe.com
2  John          Doe                 6789   john@gmail.com
3  Jane          Doe                 9876   jane@gmail.com


out = df.astype(str).groupby(['First Name', 'Last Name']).agg(', '.join)
print(out)

                        Phone Number                           Email
First Name  Last Name                                               
Jane         Doe          4321, 9876   jane@doe.com,  jane@gmail.com
John         Doe          1234, 6789   john@doe.com,  john@gmail.com

如果你想重置索引,你可以这样做,使用df.reset_index:

out = out.reset_index()
print(out)

    First Name    Last Name Phone Number                           Email
0  Jane          Doe          4321, 9876   jane@doe.com,  jane@gmail.com
1  John          Doe          1234, 6789   john@doe.com,  john@gmail.com

保存到 csv 很简单,您将使用 out.to_csv('file.csv')


附录:删除重复项

out = df.astype(str).groupby(['First Name', 'Last Name'])\
                .agg(lambda x: ', '.join(x.drop_duplicates().values))

【讨论】:

  • 很好地保持答案有限,易于阅读和简单 (+1)
  • 谢谢!有效 !您是否知道如何在相同的代码中嵌入一种使用相同代码删除“电话”或“电子邮件”列中的重复项的方法?就像在“电话”列中没有像“1234,1234,1234,6789”这样的值,我会有“1234,6789”?谢谢!
  • @TripleNipple 解决方案是使用drop_duplicates。检查我的编辑。
  • df.insert(0,"Name",[" ".join(i) for i in zip(df["First Name"],df["Last Name"])]) 到使用一个名称创建新列。
【解决方案2】:

对于一个看起来像这样的 csv 文件(有点格式以删除不必要的空格):

First Name|Last Name|Phone Number|Email
John|Doe|1234|john@doe.com
Jane|Doe|4321|jane@doe.com
John|Doe|6789|john@gmail.com
Jane|Doe|9876|jane@gmail.com

您可以按如下方式使用 pandas 来组合相似的列(基于名字和姓氏):

import pandas as pd

df = pd.read_csv("/tmp/test.csv", sep="|")
df_combined = df.groupby(["First Name", "Last Name"], as_index=False).agg({"Phone Number":lambda x: ', '.join(str(i) for i in list(x)), "Email": lambda x: ', '.join(str(i) for i in list(x))})
df_combined.to_csv("/tmp/combined_data.csv", sep="|", index=False)

输出文件如下所示:

First Name|Last Name|Phone Number|Email
Jane|Doe|4321, 9876|jane@doe.com, jane@gmail.com
John|Doe|1234, 6789|john@doe.com, john@gmail.com

【讨论】:

  • 感谢您的努力!
猜你喜欢
  • 2012-12-14
  • 1970-01-01
  • 2018-12-23
  • 2016-02-22
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 2018-07-27
  • 2018-10-23
相关资源
最近更新 更多