【问题标题】:Python: Merge Pandas Data Frame with Pivot TablePython:将 Pandas 数据框与数据透视表合并
【发布时间】:2018-01-31 00:02:04
【问题描述】:

我有以下两个要合并的数据框。

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 需要几天时间。

【问题讨论】:

  • 你能用示例数据发布你是如何到达 df2 的吗?
  • df2 是什么意思?如果你申请我要到达的数据框,我找出来,哪个时间和站属于第一个id。然后我与枢轴数据帧进行比较,得到相同时间和站点的值,然后继续下一行。因此我创建了一个 for 循环,但它不是那么快。这就是我想通过合并数据来做到这一点的原因。
  • 对不起,我看错了-pivot 数据框。你有样本数据来重新创建这个吗?我想知道是否有更好/更简单的方法来解决这个问题。
  • 在所有值都低于彼此之前。然后我使用 pandas.pivot_table() 聚合所有时间并将站点切换到列名。
  • 那么你应该在你的枢轴之前对数据框执行合并,正如我在下面的回答中提到的那样。

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


【解决方案1】:

我猜你在 pandas 中使用 pivotpivot_table 获得了数据框 pivot,如果你可以使用在数据透视之前拥有的数据框执行合并,它应该可以正常工作。

否则,您将不得不在合并之前使用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')

【讨论】:

  • 这可能是一个很好的解决方案。我明天试试。也许会出现“时间”问题,因为原始数据框包含几百万行。因此我希望数据透视表对快速合并更有用。
  • 如果您的问题与计算问题有关,可以考虑按时间段对数据帧进行分块,并在连接之前合并这些时间块。这样,您将执行几个较小的合并。它的代码会稍长一些,但会为您节省大量时间。
  • 我尝试将 df 与原始数据合并,但结果中的值为 nan。我在上面扩展了我的描述。你知道为什么没有正确的值吗?
  • 我对我的答案进行了编辑以匹配您的答案。然而,这并不能解决 NaN 问题。您的['time','station'] 列的类型在 df1 和 df2 中是否相同?
  • 是的,你是对的!我将 d1.head(100) 保存到一个额外的变量中,但忘记将时间列的数据类型更改为该变量的日期时间。然后就可以了,谢谢!当我尝试合并整个 df1 时,我应该使用循环创建块吗?例如,要每 1000 行创建一个 chunk1 和 chunk2,将其合并并将其附加到“合并”-df?还是有更快的解决方案?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 2023-03-23
  • 2022-07-26
  • 1970-01-01
  • 2021-06-25
  • 1970-01-01
相关资源
最近更新 更多