【问题标题】:How to merge multiple(more than 2) csv files based on their common column?如何根据公共列合并多个(超过 2 个)csv 文件?
【发布时间】:2019-08-14 07:59:47
【问题描述】:

现在我有 50 个具有相同列的 CSV 文件,如下所示:

gdp1950.csv

id,gdp
a,100
b,200
c,300

gdp1951.csv

id,gdp
a,400
b,500
c,600

...

gdp2000.csv

id,gdp
a,700
b,800
c,900

我要做的是像这样合并上面的 csv 文件:

id,gdp1950,gdp1951,...,gdp2000
a,100,400,...,700
b,200,500,...,800
c,300,600,...,900

该任务需要通过 Python 在 jupyter notebook 中完成。有什么想法吗?

【问题讨论】:

  • 是的。编码它。将所有文件名放在一个列表中。创建一个字典,以 ac 作为键,空列表作为值。创建一个键 header,其值为 ["id",] 循环遍历您的文件名列表。使用文件名列表读取每个文件,解析值,将它们添加到键 ["a".."c"] 的列表中 - 将文件名添加到键 ["header"] 的值中。然后把解析出来的数据写出来。如果您有具体问题,请回来 - SO 没有代码编写服务。谢谢。
  • 为什么不试试pandasmerge
  • @Wen-Ben 我把自己定位在标签上——我不会为他/她编码——没有熊猫标签。这是一个没有任何问题陈述的不费力的问题 - 因此要广泛回答。
  • @PatrickArtner 我同意你的观点,所以我只是提供一般的想法,让他/她自己弄清楚

标签: python python-3.x csv


【解决方案1】:

您可以使用一个名为 pandas 的库,它非常适合此任务:

from functools import reduce
dfs = [pd.read_csv(f"gdp{i}.csv") for i in range(1950, 2001)]
df = reduce(lambda df1, df2: pd.merge(left=df1, right=df2, on=["id"], how="inner"), dfs)

【讨论】:

  • 您的代码将列命名为 gdpxgdpy,而不是文件名。
【解决方案2】:

您可以使用 vanilla python 解决它,不需要第三方库或模块:

outputDict = {"id" : []}
for i in range(1950, 2001):
    outputDict["id"].append(f"gdp{i}")
    with open(f"gdp{i}.csv", "r") as file:
        file.readline()    # We don't need that line
        for line in file:
            key, value = line.rstrip("\n").split(",")
            if key in outputDict:
                outputDict[key].append(value)
            else:
                outputDict[key] = [value]

with open("gdpTotal.csv", "w") as output:
     output.write("\n".join(",".join((k, *[i for i in v])) for k, v in outputDict.items()))    # Convert the dictionary of lists into a suitable string for file writing

最后一行"\n".join(",".join((k, *[i for i in v])) for k, v in outputDict.items()) 相当于(结果相同但过程不同)

for k, v in outputDict.items():
    output.write(f"{k},{','.join(v)}\n")

另外,您可以使用collections.defaultdict 删除 if 语句。此外,它的速度稍快。

outputDict = defaultdict(list)
for i in range(1950, 2001):
    outputDict["id"].append(f"gdp{i}")
    with open(f"gdp{i}.csv", "r") as file:
        file.readline()
        for line in file:
            key, value = line.rstrip("\n").split(",")
            outputDict[key].append(value)

with open("gdpTotal.csv", "w") as output:
     output.write("\n".join(",".join((k, *[i for i in v])) for k, v in outputDict.items()))

使用timeit.timeit(带有参数number = 100)它需要0.825195171秒第一个代码(0.8229198819999999第二个代码)。 取而代之的是熊猫的用法:

from functools import reduce
import pandas as pd
dfs = [pd.read_csv(f"gdp{i}.csv") for i in range(1950, 2001)]
df = reduce(lambda df1, df2: pd.merge(left=df1, right=df2, on=["id"], how="inner"), dfs)
df.to_csv("gdpTotal.csv")

需要32.095738075999996 秒。它可能需要更少的行,但速度要慢得多。

【讨论】:

    猜你喜欢
    • 2022-11-22
    • 2010-10-24
    • 1970-01-01
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-22
    • 1970-01-01
    • 2021-04-28
    相关资源
    最近更新 更多