Python:将Pandas数据框与数据透视表

时间:2017-08-22 15:46:17

标签: python-3.x pandas merge pivot-table

我想要合并以下两个数据帧。

df1:
     id   time                  station
0     a   22.08.2017 12:00:00   A1
1     b   22.08.2017 12:00:00   A3
2     a   22.08.2017 13:00:00   A2
...

pivot:
      station               A1     A2     A3
0     time
1     22.08.2017 12:00:00   10     12     11
2     22.08.2017 13:00:00   9      7      3
3     22.08.2017 14:00:00   2      3      4
4     22.08.2017 15:00:00   3      2      7
...

应该看起来像:

merge:

     id   time                  station   value
0     a   22.08.2017 12:00:00   A1        10
1     b   22.08.2017 12:00:00   A3        11
2     a   22.08.2017 13:00:00   A2        7
...

现在我想在数据框中添加一个具有来自数据透视表的正确值的列。我没有包括合并的列标签。 我构建了类似的东西,但它不起作用:

merge = pd.merge(df1, pivot, how="left", left_on=["time", "station"], right_on=["station", pivot.columns])

任何帮助?

修改

根据建议,我尝试使用以下数据而不是数据透视表:

df2:
time                 station   value
22.08.2017 12:00:00  A1        10
22.08.2017 12:00:00  A2        12
22.08.2017 12:00:00  A3        11
              ...
22.08.2017 13:00:00  A1        9
22.08.2017 13:00:00  A2        7
22.08.2017 13:00:00  A3        3

该表包含每个时间戳的大约1300个不同的站。总而言之,我有超过115.000.000行。我的df1有5.000.000行。

现在我尝试合并df1.head(100)和df2,但结果中所有值都是nan。因此我使用了这个:

merge = pd.merge(df1.head(100), df2, how="left", on=["time", "station"])

另一个问题是合并需要几分钟,所以我希望整个df1需要几天时间。

1 个答案:

答案 0 :(得分:1)

我猜你在pandas中使用pivotpivot得到了数据帧pivot_table,如果你可以使用你在数据透视之前使用的数据帧来执行合并它应该可以正常工作。

否则,您必须在合并之前使用melt撤消数据透视:

melt = pd.concat([pivot[['time']],pivot[['A1']].melt()],axis = 1)
melt = pd.concat([melt,pd.concat([pivot[['time']],pivot[['A2']].melt()],axis = 1)])
melt = pd.concat([melt,pd.concat([pivot[['time']],pivot[['A3']].melt()],axis = 1)])
melt.columns = ['time','station','value']

然后按照您的预期执行合并:

my_df.merge(melt,on = ['time','station'])

    id  time    station value
0   a   time1   A1      10
1   b   time1   A3      11
2   a   time2   A2      7

修改

如果您的数据框架与编辑中的数据框架一样大,那么您确实必须在它们的块上执行合并。您可以尝试将其缩小为数据帧。

首先,对df1进行排序,以便只有接近的时间值:

df1.sort_values('time',inplace = True)

然后你将它分块,以确定你可能需要的所有行的方式对第二个数据帧进行分块,然后合并这些块:

chunk1 = df1.head(100)
chunk2 = df2.loc[df2.time.between(chunk1.time.min(),chunk1.time.max())]
merge = chunk1.merge(chunk2,on = ['time','station'],how = 'left')