根据特定列合并多个 CSV 文件 - Python
Posted
技术标签:
【中文标题】根据特定列合并多个 CSV 文件 - Python【英文标题】:Merging multiple CSV files based on specific column - Python 【发布时间】:2021-04-28 04:33:35 【问题描述】:我正在尝试在 Pandas 中合并大约 101 个 CSV 文件。每个文件都有 2 个时间列和一个“值”列。我想保留 2 次列,因为它们在 CSV 文件中是相同的,然后将 101 个 CSV 中的每一个的“值”列合并到一个新的 CSV 文件中。
使用 pd.merge 我可以使用以下合并 2 个文件
data1 = 'time': ['00:00','01:00','02:00'],
'local_time': ['09:30','10:30','11:30'],
'value': ['265.591','330.766','360.962']
data2 = 'time': ['00:00','01:00','02:00'],
'local_time': ['09:30','10:30','11:30'],
'value': ['521.217','588.034','588.034']
df_1 = pd.DataFrame(data1)
df_2 = pd.DataFrame(data2)
locs = ['_A11','_B10']
df_test = pd.merge(df_1,df_2, on=['time','local_time'], how='inner', suffixes = (locs)
)
print(df_test)
这会产生:
time local_time value_A11 value_B10
0 00:00 09:30 265.591 521.217
1 01:00 10:30 330.766 588.034
2 02:00 11:30 360.962 588.034
但是,我不太确定如何组合接下来的 99 个 csv 文件,或者这是否是完成这项任务的最佳方式。
我的目标是:
time local_time value_A11 value_B10 value_B11 ...
0 00:00 09:30 265.591 521.217 123 ...
1 01:00 10:30 330.766 588.034 456 ...
2 02:00 11:30 360.962 588.034 789 ...
任何帮助将不胜感激!
编辑 1:
Colin 的示例有效,但是我一直在将数据帧加载到这样的数组中:
import glob
import os
# create and sort list of file names in folder
fl = glob.glob('*.csv')
sorted_fl = sorted(fl)
# open csv files from list and store in df
df_list = [pd.read_csv(f, header=3) for f in sorted_fl]
#test df
df_list[0]
我想知道如何修改 for 循环以便它可以为数组提供数据?再次感谢!
编辑 2:从答案到编辑 1 的错误
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-144-772c1d15f228> in <module>
14 # loop through each dataframe and merge it with existing one
15 for i, df in enumerate(df_list[1:]):
---> 16 df_output = pd.merge(df_list[0], df, on=['time','local_time'], how='inner', suffixes = (['_' + str(i), '_' + str(i+1)]))
~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/reshape/merge.py in merge(left, right, how, on, left_on, right_on, left_index, right_index, sort, suffixes, copy, indicator, validate)
79 copy=copy,
80 indicator=indicator,
---> 81 validate=validate,
82 )
83 return op.get_result()
~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/reshape/merge.py in __init__(self, left, right, how, on, left_on, right_on, axis, left_index, right_index, sort, suffixes, copy, indicator, validate)
628 # validate the merge keys dtypes. We may need to coerce
629 # to avoid incompat dtypes
--> 630 self._maybe_coerce_merge_keys()
631
632 # If argument passed to validate,
~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/reshape/merge.py in _maybe_coerce_merge_keys(self)
1136 inferred_right in string_types and inferred_left not in string_types
1137 ):
-> 1138 raise ValueError(msg)
1139
1140 # datetimelikes must match exactly
ValueError: You are trying to merge on object and float64 columns. If you wish to proceed you should use pd.concat
编辑 3
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-cce982321079> in <module>
11
12 # change datatype to datetime for first df
---> 13 df['local_time'] = pd.to_datetime(df_list[0]['local_time'])
14 df['time'] = pd.to_datetime(df_list[0]['time'])
15
NameError: name 'df' is not defined
【问题讨论】:
【参考方案1】:这似乎是一个不错的方法。我只是设置了一些不同的合并和后缀,这样你就可以遍历每个数据帧,如下所示。每个新值列都将合并到 df_test。
编辑:更新代码以配合 OP 的编辑
编辑 2: 修复了 OP 错误的数据类型
import pandas as pd
import glob
import os
# create and sort list of file names in folder
fl = glob.glob('*.csv')
sorted_fl = sorted(fl)
# open csv files from list and store in df
df_list = [pd.read_csv(f, header=3) for f in sorted_fl]
# change datatype to datetime for first df
df['local_time'] = pd.to_datetime(df_list[0]['local_time'])
df['time'] = pd.to_datetime(df_list[0]['time'])
# loop through each dataframe and merge it with existing one
for i, df in enumerate(df_list[1:]):
# change datatype to datetime
df['local_time'] = pd.to_datetime(df['local_time'])
df['time'] = pd.to_datetime(df['time'])
df_output = pd.merge(df_list[0], df, on=['time','local_time'], how='inner', suffixes = (['_' + str(i), '_' + str(i+1)]))
#print(df_output)
'''
time local_time value_0 value_1 value_2 value_3
0 00:00 09:30 738.591 265.591 521.217 856.217
1 01:00 10:30 217.766 330.766 588.034 346.034
2 02:00 11:30 295.962 360.962 588.034 645.034
'''
【讨论】:
感谢科林。有效!但是,我确实没有提到我正在将所有数据帧加载到一个名为 df_list 的数组中。我需要在 for 循环中进行哪些更改才能使其与数组一起使用?我已经编辑了我的问题以获取完整的详细信息和我的代码。感谢您的帮助! Aaron,我更新了代码以使用您的列表。让我知道它是否有效。 嘿科林,再次感谢您的帮助!我从您提供的代码中得到了很多错误。我已在原始问题的编辑 2 中粘贴了错误,以向您展示我得到了什么。 Aaron,我添加了四行应该可以解决您的错误。确保你只是 pd.to_datetime 的时间和 local_time 的第一个 df 和通过循环的每次迭代 嗨科林。我收到一个新错误,但看起来更好。我尝试定义“df”并将其更改为不同的变量,但没有任何成功。我已将新错误发布到另一个编辑。非常感谢您的帮助!以上是关于根据特定列合并多个 CSV 文件 - Python的主要内容,如果未能解决你的问题,请参考以下文章
使用 Python 字典在 Python 中合并 CSV 文件
使用Python Dictionary在Python中合并CSV文件