使用numpy/pandas按时间戳合并时间序列数据

23

我有来自三个完全不同的传感器源的时间序列数据,存储在CSV文件中,并希望将它们合并成一个大的CSV文件。

我已经使用numpy的genfromtxt将它们读入了numpy数组,但是我不确定下一步该做什么。

基本上,我手头的情况是这样的:

表1:

timestamp    val_a   val_b   val_c

表格2:

timestamp    val_d   val_e   val_f   val_g

表格 3:

timestamp    val_h   val_i

所有时间戳均为UNIX毫秒级时间戳,数据类型为numpy.uint64。

我的要求是:

timestamp    val_a   val_b   val_c   val_d   val_e   val_f   val_g   val_h   val_i

...其中所有数据按时间戳组合并排序。这三个表格中的每一个都已经按时间戳排序。 由于数据来自不同的来源,不能保证一张表格中的时间戳也出现在另外两张表格中,反之亦然。这种情况下,空缺值应该标记为N/A。

到目前为止,我尝试使用Pandas将数据转换如下:

df_sensor1 = pd.DataFrame(numpy_arr_sens1)
df_sensor2 = pd.DataFrame(numpy_arr_sens2)
df_sensor3 = pd.DataFrame(numpy_arr_sens3)

我尝试使用pandas.DataFrame.merge,但我相当确定那对我现在想做的事情行不通。有人能指点我一下吗?


2
你能展示一下你尝试使用merge的代码吗?例如,如果你执行了merged = pd.merge(df_sensor1, df_sensor_2, on='timestamp'),然后对df_seonsor3重复操作,或者如果你在所有数据框上都将索引设置为时间戳,那么你只需要执行pd.concat([df_sensor_1, df_seonsor2, df_sensor3]) - EdChum
谢谢您的快速回答!我按照您的要求使用了merge,但是它似乎只执行内连接,因此只有在所有表中都有时间戳的数据点才会被写入合并后的表中。我也尝试过外连接,虽然包含了所有数据,但排序也不正确。不过我刚刚尝试了concat。我执行了merged = pd.concat([df_sensor1, df_sensor2, df_sensor3], axis=1)merged.to_csv('out.csv', sep=';', header=True, index=True, na_rep='N/A'),看起来已经完成了任务。我明天还需要验证一下。 - vind
1个回答

22

我认为您可以简单地:

  • timestamp定义为每个DataFrameindex(使用set_index
  • 使用join方法并选择'outer'方式合并它们
  • 如有需要,将timestamp转换为datetime

这是它的样子。

# generating some test data
timestamp = [1440540000, 1450540000]
df1 = pd.DataFrame(
    {'timestamp': timestamp, 'a': ['val_a', 'val2_a'], 'b': ['val_b', 'val2_b'], 'c': ['val_c', 'val2_c']})
# building a different index
timestamp = timestamp * np.random.randn(abs(1))
df2 = pd.DataFrame(
    {'timestamp': timestamp, 'd': ['val_d', 'val2_d'], 'e': ['val_e', 'val2_e'], 'f': ['val_f', 'val2_f'],
     'g': ['val_g', 'val2_g']}, index=index)
# keeping a value in common with the first index
timestamp = [1440540000, 1450560000]
df3 = pd.DataFrame({'timestamp': timestamp, 'h': ['val_h', 'val2_h'], 'i': ['val_i', 'val2_i']}, index=index)

# Setting the timestamp as the index
df1.set_index('timestamp', inplace=True)
df2.set_index('timestamp', inplace=True)
df3.set_index('timestamp', inplace=True)

# You can convert timestamps to dates but it's not mandatory I think
df1.index = pd.to_datetime(df1.index, unit='s')
df2.index = pd.to_datetime(df2.index, unit='s')
df3.index = pd.to_datetime(df3.index, unit='s')

# Just perform a join and that's it
result = df1.join(df2, how='outer').join(df3, how='outer')
result

result


2
如果您使用此解决方案并且拥有许多表(或者数量未知的动态表),则可以将join操作放在reduce函数中,这意味着代码量大大减少。此外,我相信pandas.merge()会概括上面使用的join()方法。首先,from functools import reduce,然后result = reduce(lambda left, right: pd.merge(left, right, left_on='timestamp', right_on='timestamp', how='outer'), df_list),其中最后一个参数df_list是您的数据帧列表,例如df_list = [df1, df2, df3, ..., df_n] - n1k31t4
@n1k31t4 另外,还应将left_indexright_index设置为True。因此我们有pd.merge(left,right,left_on ='timestamp',right_on ='timestamp',how ='outer',lefT_index = True,right_index = True) - arash javanmard
根据文档,@n1k31t4,join可以接收一个列表:"通过传递一个列表,可以高效地一次性按索引连接多个DataFrame对象。" - Jérôme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接