我正在尝试将100多个csv文件合并为一个csv文件。每个文件都有一个时间戳列和一个数据列。一些文件具有相同的数据列,但时间戳不同。
我通过使用os.walk()搜索目录然后遍历此列表,将每个文件作为数据框打开并将其与输出数据框合并来获取文件名列表。这开始是空的,但会在每个循环中添加数据。
这是代码的要点:
output = pd.DataFrame(columns=['TimeStamp'])
for filename in file_list:
df = pd.read_csv(filename, sep=',', skiprows=2, header=None, encoding='utf-16')
# convert dtypes
df['TimeStamp'] = pd.to_datetime(df['TimeStamp'], dayfirst=True)
df[tag_name] = pd.to_numeric(df[tag_name])
#tag_name comes from a dictionary matching the file with a label
# here are the two approaches I'm trying:
# approach 1
output= output.merge(df, how='outer', on='TimeStamp', sort=True)
# approach 2 - this has the output df initialised with the columns from the tag_name dictionary
output = output.merge(df, how='outer', on=['TimeStamp', tag_name], sort=True)
以下是数据示例:
'TimeStamp', 'Meter 1'
2019-01-01 00:00, 12
2019-01-01 01:00, 17
2019-01-01 02:00, 10
'TimeStamp', 'Meter 1'
2019-01-01 03:00, 13
2019-01-01 04:00, 20
2019-01-01 05:00, 9
'TimeStamp', 'Meter 2'
2019-01-01 00:00, 1
2019-01-01 01:00, 6
2019-01-01 02:00, 5
上述3个项目的预期结果:
'TimeStamp', 'Meter 1', 'Meter 2'
2019-01-01 00:00, 12, 1
2019-01-01 01:00, 17, 6
2019-01-01 02:00, 10, 5
2019-01-01 03:00, 13,
2019-01-01 04:00, 20,
2019-01-01 05:00, 9,
方法1的结果
'TimeStamp', 'Meter 1', 'Meter 1_x', 'Meter 2'
2019-01-01 00:00, 12, , 1
2019-01-01 01:00, 17, , 6
2019-01-01 02:00, 10, , 5
2019-01-01 03:00, , 13,
2019-01-01 04:00, , 20,
2019-01-01 05:00, , 9,
方法2的结果
'TimeStamp', 'Meter 1', 'Meter 2'
2019-01-01 00:00, 12,
2019-01-01 00:00, , 1
2019-01-01 01:00, 17,
2019-01-01 01:00, , 6
2019-01-01 02:00, 10,
2019-01-01 02:00, , 5
2019-01-01 03:00, 13,
2019-01-01 04:00, 20,
2019-01-01 05:00, 9,
他们都快到了,但还不完全。有没有一种方法可以通过合并实现这一目标,或者我是否需要完全不同的方法?
我试图从方法1中找到将匹配的列加在一起的方法,但是每次列的数量都是不规则的。我会在早上再试一次。
编辑: 链接到该问题的另一个问题虽然是一个很好的资源,但实际上并不能解决这种情况,因为有重复的列名需要合并在一起。该答案中最接近的部分使用带有functools.partial的解决方案,但是说如果您有重复的列名,则可能需要使用lambda,而无需进一步说明。我不知道如何用lambda函数实现该解决方案。
我在少量文件上尝试了这种方法,但没有lambda函数也没有失败,但是在我自己的代码中确实产生了与方法2相同的结果。但是,它比我的方法快得多。
from functools import reduce, partial
outer_merge = partial(pd.merge, how='outer')
reduce(outer_merge, dfs)
我认为这是大熊猫认为时间戳不相等的问题。当我将它们保留为字符串时,也会发生同样的事情。
修改2: 在文本编辑器中看到的实际csv文件的顶部:
"sep=,"
"","Meter_tag",""
"Time","Average(Time Weighted)",""
"01/06/2017 00:00:00","0.000",""
修改3: 感谢Valentino在此方面的帮助。我最终使用了一种解决方法,因此我的输出就像上面的方法2一样,但是我只是每小时对其进行分组,从而将多余的行压缩了下来。它只是将实际数据与零进行求和,因此求和操作不会更改数据。
output= output.groupby(pd.Grouper(key='TimeStamp', freq='1H')).sum().reset_index()
答案 0 :(得分:2)
比您想象的要容易。
output= output.merge(df, how='outer', sort=True)
只需删除on
关键字参数。如果on=None
(默认设置),则docs表示:
如果on为None且未在索引上合并,则默认为两个DataFrame中列的交集。
使用三个示例文件,它将为您提供:
TimeStamp Meter 1 Meter 2
0 2019-01-01 00:00:00 12 1.0
1 2019-01-01 01:00:00 17 6.0
2 2019-01-01 02:00:00 10 5.0
3 2019-01-01 03:00:00 13 NaN
4 2019-01-01 04:00:00 20 NaN
5 2019-01-01 05:00:00 9 NaN
请注意:如果某些文件具有重叠的TimeStamp
值和相同的列,则将以重复的TimeStamp
值结尾。您的样本文件中没有涉及这种情况,因此我认为您确定这种情况永远不会发生。