【问题标题】:How to map data from one dataframe into a column in another dataframe?如何将数据从一个数据帧映射到另一个数据帧的列?
【发布时间】:2021-08-09 02:56:41
【问题描述】:

我有两个独立的数据框,代表不同类型的基于时间的数据。一个包含分布在几个月内的数十万个时间戳。此数据框具有代表一年中的月份、一天中的时间和测量温度的列。第二个数据框包含每个月/小时组合的替换温度。数据大致如下:

df1

Timestamp Month Hour Temperature
1/1/2021 00:00:00 1 0 10
1/1/2021 00:00:05 1 0 11
1/1/2021 00:00:07 1 0 8
1/1/2021 00:00:15 1 0 12
1/1/2021 00:01:00 1 1 13

等等

df2

Hour Jan Feb Mar Apr etc
0 9 12 10 12 etc
1 10 11 14 15 etc
2 8 7 12 16 etc

df2 包含一天中每个小时的行,以及一年中每个月的列(在真实数据集中,月份是数字,我写了名称以使描述清晰)。

我需要将 df2 中包含的月份/小时的数据映射到 df 1 中的温度列。所以 df1 编辑后应该如下所示。

新的 df1

Timestamp Month Hour Temperature
1/1/2021 00:00:00 1 0 9
1/1/2021 00:00:05 1 0 9
1/1/2021 00:00:07 1 0 9
1/1/2021 00:00:15 1 0 9
1/1/2021 00:01:00 1 1 10

我已经使用嵌套的 for 循环使其工作,如下所示:

for month in df2.columns:
    for hour in df2.index:
        dT = df2.loc[hour, month]
        df1.loc[(df1['Month'] == month) & (df1['Hour'] == hour), 'Temperature'] = dT

嵌套的 for 循环遍历 df2 中的所有月份和时间,找到 df1 中具有匹配月份和时间的单元格,然后将温度设置为等于从 df2 中读取的温度。

但是这段代码既难以阅读又执行起来超级慢。有人知道更好的方法吗??

谢谢!

【问题讨论】:

  • 你能测试my answer 并给我关于运行时间的反馈吗?可以通过跳过提取月份名称的步骤并改用第二个数据框来加快速度。让我知道……

标签: python pandas dataframe


【解决方案1】:

让我们按顺序调用 df1 和 df2 两个数据帧。

首先,确保 Timestamp 是 datetime 并提取月份短名称(我们也可以将月份编号映射到短名称)

df1['Timestamp'] = pd.to_datetime(df1['Timestamp'])
df1['Month_name'] = df1['Timestamp'].dt.month_name().str[:3]

注意。如果速度很关键,则跳过上述步骤并重新设计您的 df2 以使用月份数字代替月份名称作为列,然后在最后一步中使用 df1 的“月份”列执行合并

然后重做 df2 以取消堆叠月份(这可以在下一步中直接应用或保存在变量中):

df2.set_index('Hour').unstack().rename('Temperature')

最后merge两人:

df1.merge(df2.set_index('Hour').unstack().rename('Temperature'),
          left_on=['Month_name', 'Hour'],
          right_index=True,
          suffixes=('_old', ''),
         )

输出:

            Timestamp  Month  Hour  Temperature_old Month_name  Temperature
0 2021-01-01 00:00:00      1     0               10        Jan            9
1 2021-01-01 00:00:05      1     0               11        Jan            9
2 2021-01-01 00:00:07      1     0                8        Jan            9
3 2021-01-01 00:00:15      1     0               12        Jan            9
4 2021-01-01 00:01:00      1     1               13        Jan           10

如果您只想保留新的温度,请添加.drop(['Month', 'Temperature_old'], axis=1)

【讨论】:

  • 嗨 mozway。感谢您的建议!不幸的是,它不起作用。当我运行 .merge 步骤时,我收到一条错误消息,指出它正在尝试合并 int 和 object 列,并且我应该使用 pd.concat 代替。这是具体错误: ValueError: You are trying to merge on int32 and object columns。如果你想继续,你应该使用 pd.concat。我对这个错误感到非常困惑,因为当我检查列类型时,它们确实排成一行。月份是 int(例如,“Jan”现在是“1”)。小时是整数。 df2.unstack().rename('Temperature') 的索引是一个元组,但 left_on 也是。有什么想法吗?
  • 索引怎么是元组?您的数据集与示例不同吗?可以提供吗?
  • 拆散df2时出现问题。最初“小时”是索引(我很抱歉最初没有指定)。当我取消堆叠时,它成为(月,小时)的多级索引。但是您提供的代码看起来需要一个元组,所以我不认为这是一个问题。我可以上传 df2,但不能上传 df1。有什么好的方法吗?我以前从未问过关于 SO 的问题,也没有明确的方法。
猜你喜欢
  • 2019-10-17
  • 2022-01-24
  • 2017-04-20
  • 1970-01-01
  • 2022-10-12
  • 2023-03-21
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多