pandas - 如何合并 DataFrame,以便将与*日期*对应的一个数据框的值应用于另一个 DataFrame 的所有日期的所有*时间*?

标签 pandas datetime dataframe merge datetimeindex

我有两个 DataFrame。有一组与特定时间和日期相对应的值 (df_1)。另一个有一组与特定日期相对应的值 (df_2)。我想合并这些 DataFrame,以便将日期的 df_2 值应用于相应日期的 df_1 的所有时间

所以,这是df_1:

|DatetimeIndex          |value_1|
|-----------------------|-------|
|2015-07-18 13:53:33.280|10     |
|2015-07-18 15:43:30.111|11     |
|2015-07-19 13:54:03.330|12     |
|2015-07-20 13:52:13.350|13     |
|2015-07-20 16:10:01.901|14     |
|2015-07-20 16:50:55.020|15     |
|2015-07-21 13:56:03.126|16     |
|2015-07-22 13:53:51.747|17     |
|2015-07-22 19:45:14.647|18     |
|2015-07-23 13:53:29.346|19     |
|2015-07-23 20:00:30.100|20     |

这里是df_2:

|DatetimeIndex|value_2|
|-------------|-------|
|2015-07-18   |100    |
|2015-07-19   |200    |
|2015-07-20   |300    |
|2015-07-21   |400    |
|2015-07-22   |500    |
|2015-07-23   |600    |

我想像这样合并它们:

|DatetimeIndex          |value_1|value_2|
|-----------------------|-------|-------|
|2015-07-18 00:00:00.000|NaN    |100    |
|2015-07-18 13:53:33.280|10.0   |100    |
|2015-07-18 15:43:30.111|11.0   |100    |
|2015-07-19 00:00:00.000|NaN    |200    |
|2015-07-19 13:54:03.330|12.0   |200    |
|2015-07-20 00:00:00.000|NaN    |300    |
|2015-07-20 13:52:13.350|13.0   |300    |
|2015-07-20 16:10:01.901|14.0   |300    |
|2015-07-20 16:50:55.020|15.0   |300    |
|2015-07-21 00:00:00.000|NaN    |400    |
|2015-07-21 13:56:03.126|16.0   |400    |
|2015-07-22 00:00:00.000|NaN    |500    |
|2015-07-22 13:53:51.747|17     |500    |
|2015-07-22 19:45:14.647|18     |500    |
|2015-07-23 00:00:00.000|NaN    |600    |
|2015-07-23 13:53:29.346|19     |600    |
|2015-07-23 20:00:30.100|20     |600    |

因此,value_2 整天都存在。

这叫什么类型的合并?怎么办?

DataFrames 的代码如下:

import pandas as pd

df_1 = pd.DataFrame(
    [
        [pd.Timestamp("2015-07-18 13:53:33.280"), 10],
        [pd.Timestamp("2015-07-18 15:43:30.111"), 11],
        [pd.Timestamp("2015-07-19 13:54:03.330"), 12],
        [pd.Timestamp("2015-07-20 13:52:13.350"), 13],
        [pd.Timestamp("2015-07-20 16:10:01.901"), 14],
        [pd.Timestamp("2015-07-20 16:50:55.020"), 15],
        [pd.Timestamp("2015-07-21 13:56:03.126"), 16],
        [pd.Timestamp("2015-07-22 13:53:51.747"), 17],
        [pd.Timestamp("2015-07-22 19:45:14.647"), 18],
        [pd.Timestamp("2015-07-23 13:53:29.346"), 19],
        [pd.Timestamp("2015-07-23 20:00:30.100"), 20]
    ],
    columns = [
        "datetime",
        "value_1"
    ]
)
df_1.index = df_1["datetime"]
del df_1["datetime"]
df_1.index = pd.to_datetime(df_1.index.values)

df_2 = pd.DataFrame(
    [
        [pd.Timestamp("2015-07-18 00:00:00"), 100],
        [pd.Timestamp("2015-07-19 00:00:00"), 200],
        [pd.Timestamp("2015-07-20 00:00:00"), 300],
        [pd.Timestamp("2015-07-21 00:00:00"), 400],
        [pd.Timestamp("2015-07-22 00:00:00"), 500],
        [pd.Timestamp("2015-07-23 00:00:00"), 600]
    ],
    columns = [
        "datetime",
        "value_2"
    ]
)
df_2
df_2.index = df_2["datetime"]
del df_2["datetime"]
df_2.index = pd.to_datetime(df_2.index.values)

最佳答案

解决方案
构造一个新索引,该索引是两者的并集。然后结合使用reindexmap

idx = df_1.index.union(df_2.index)

df_1.reindex(idx).assign(value_2=idx.floor('D').map(df_2.value_2.get))

                         value_1  value_2
2015-07-18 00:00:00.000      NaN      100
2015-07-18 13:53:33.280     10.0      100
2015-07-18 15:43:30.111     11.0      100
2015-07-19 00:00:00.000      NaN      200
2015-07-19 13:54:03.330     12.0      200
2015-07-20 00:00:00.000      NaN      300
2015-07-20 13:52:13.350     13.0      300
2015-07-20 16:10:01.901     14.0      300
2015-07-20 16:50:55.020     15.0      300
2015-07-21 00:00:00.000      NaN      400
2015-07-21 13:56:03.126     16.0      400
2015-07-22 00:00:00.000      NaN      500
2015-07-22 13:53:51.747     17.0      500
2015-07-22 19:45:14.647     18.0      500
2015-07-23 00:00:00.000      NaN      600
2015-07-23 13:53:29.346     19.0      600
2015-07-23 20:00:30.100     20.0      600

说明

  • 将两者结合起来应该是不言自明的。但是,在进行并集时,我们也会自动获得排序索引。真方便!
  • 当我们使用这个新的、改进的索引联合重新索引 df_1 时,某些索引值将不会出现在 df_1 的索引中。如果不指定其他参数,那些先前不存在的索引的列值将是 np.nan,这正是我们想要的。
  • 我使用分配来添加列。
    • 我认为它更干净
    • 它不会覆盖我正在使用的数据框
    • 管道传输良好
  • idx.floor('D') 为我提供了日期,同时保持了 pd.DatetimeIndex 的特征。这让我可以在它之后映射
  • pd.Index.map 采用可调用
  • 我传递了 df_2.value_2.get,感觉很像 dict.get(我喜欢)

回复评论
假设 df_2 有多个列。我们可以使用 join 代替

df_1.join(df_2.loc[idx.date].set_index(idx), how='outer')

                         value_1  value_2
2015-07-18 00:00:00.000      NaN      100
2015-07-18 13:53:33.280     10.0      100
2015-07-18 15:43:30.111     11.0      100
2015-07-19 00:00:00.000      NaN      200
2015-07-19 13:54:03.330     12.0      200
2015-07-20 00:00:00.000      NaN      300
2015-07-20 13:52:13.350     13.0      300
2015-07-20 16:10:01.901     14.0      300
2015-07-20 16:50:55.020     15.0      300
2015-07-21 00:00:00.000      NaN      400
2015-07-21 13:56:03.126     16.0      400
2015-07-22 00:00:00.000      NaN      500
2015-07-22 13:53:51.747     17.0      500
2015-07-22 19:45:14.647     18.0      500
2015-07-23 00:00:00.000      NaN      600
2015-07-23 13:53:29.346     19.0      600
2015-07-23 20:00:30.100     20.0      600

这似乎是一个更好的答案,因为它更短。但对于单列情况来说速度较慢。无论如何,将其用于多列情况。

%timeit df_1.reindex(idx).assign(value_2=idx.floor('D').map(df_2.value_2.get))
%timeit df_1.join(df_2.loc[idx.date].set_index(idx), how='outer')

1.56 ms ± 69 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.38 ms ± 591 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

关于pandas - 如何合并 DataFrame,以便将与*日期*对应的一个数据框的值应用于另一个 DataFrame 的所有日期的所有*时间*?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46654734/

相关文章:

Java:从服务器而不是系统时钟获取当前日期和时间

python - Pandas:循环每一行,提取特征并创建新列

python - 在 Python 中使用 Pandas 删除括号 () 并后处理数据帧时出现问题

python - 在 Pandas DataFrame 的多列上使用 fillna 方法失败

python - 有没有办法对包含列表的数据框列进行排序?

python - Pandas 对特定条件进行计数和求和仅返回 nan

php - 从当前日期和时间中减去一些日期和时间即可在 PHP 中查找年龄

python - Pandas - 删除只有 NaN 值的行

python - 我如何使用 pandas 数据框,这样我只得到真实的行,如果条件不正确,我什么也得不到

python - Pandas DataFrame - 根据其他列的值填充列的 NaN