如何根据 df1 中的日期在 df2 中跨两列的日期范围值之间查找单独数据框 (df2) 中的数据
How to look up data in a separate dataframe (df2) based on date in df1 falling between date range values across two columns in df2
情况:
我有两个数据框 df1 和 df2,其中 df1 有一个基于天的日期时间索引,df2 有两个日期列 'wk start' 和 'wk end' 是每周范围以及一个数据列 'statistic'存储对应于周范围的数据。
我想做的事情:
在 df1 中添加 'statistic' 的列,由此我查找每个日期(每天,即每一行)并尝试根据该日期所在的星期找到相应的 'statistic'。
我认为答案需要将 df2 合并到 df1 中,但我不知道之后如何进行。
感谢您提供的任何帮助!谢谢!
df1:(注意:我跳过了 2019-06-12 和 2019-06-16 之间的行以保持示例简短。)
年龄
日期
2019-06-10
20
2019-06-11
21
2019-06-17
19
2019-06-18
18
df2:
周开始
周结束
统计数据
2019-06-10
2019-06-14
102
2019-06-17
2019-06-21
100
2019-06-24
2019-06-28
547
2019-07-02
2019-07-25
268
期望的输出:
年龄
统计数据
日期
:---
:--------
2019-06-10
20
102
2019-06-11
21
102
2019-06-17
19
100
2019-06-18
18
100
数据帧 d1 和 d2 的代码
import pandas as pd
import datetime
data1 = {'date': ['2019-06-10', '2019-06-11', '2019-06-17', '2019-06-18'], 'age': [20, 21, 19, 18]}
data1['date']=pd.to_datetime(data1['date'])
df1 = pd.DataFrame(data1)
df1.set_index('date', inplace=True)
data2 = {'wk start': ['2019-06-10', '2019-06-17', '2019-06-24', '2019-07-02'], 'wk end':[ '2019-06-14', '2019-06-21', '2019-06-28', '2019-07-05'], 'height': [120,121, 119, 118]}
data2['wk start']=pd.to_datetime(data2['wk start'])
data2['wk end']=pd.to_datetime(data2['wk end'])
df2 = pd.DataFrame(data2)
您可以循环遍历数据帧并在进行时对第二个数据帧进行子集化。
import pandas as pd
import datetime
data1 = {'date': ['2019-06-10', '2019-06-11', '2019-06-17', '2019-06-18'], 'age': [20, 21, 19, 18]}
data1['date']=pd.to_datetime(data1['date'])
df1 = pd.DataFrame(data1)
df1.set_index('date', inplace=True)
data2 = {'wk start': ['2019-06-10', '2019-06-17', '2019-06-24', '2019-07-02'], 'wk end':[ '2019-06-14', '2019-06-21', '2019-06-28', '2019-07-05'], 'height': [120,121, 119, 118]}
data2['wk start']=pd.to_datetime(data2['wk start'])
data2['wk end']=pd.to_datetime(data2['wk end'])
df2 = pd.DataFrame(data2)
# Loop
list1 = []
for row in df1.iterrows():
subdf = df2[(df2['wk start'] <= index) & (df2['wk end'] >= index)]
list1.append(subdf['height'].tolist()[0])
df1['height'] = list1
print(df1)
这些值与您上面显示的table(统计值)有点不同,因为您提供的代码具有不同的值和高度而不是统计值,但原理是相同的。
df[df.some_date.between(start_date, end_date)]
你可以像这样在日期列上使用 isin 方法
df[df[“日期”].isin(pd.date_range(start_date, end_date))]
按照这个
看看这个
Assign values in one dataframe if date is in date range in another dataframe and projects are equal
您可以先reset_index()
on df1
to get the date
row index back to data column. Then, cross join df1
and df2
by .merge()
with how='cross'
and then filter the result by date
field is between wk start
and wk end
using .between()
,如下;
df_merge = df1.reset_index().merge(df2, how='cross')
df_out = df_merge[df_merge['date'].between(df_merge['wk start'], df_merge['wk end'])]
或者,如果您的 Pandas 版本小于 1.2.0(2020 年 12 月发布)
df_merge = df1.reset_index().assign(key=1).merge(df2.assign(key=1), on='key').drop('key', axis=1)
df_out = df_merge[df_merge['date'].between(df_merge['wk start'], df_merge['wk end'])]
结果:
print(df_out)
date age wk start wk end height
0 2019-06-10 20 2019-06-10 2019-06-14 120
4 2019-06-11 21 2019-06-10 2019-06-14 120
9 2019-06-17 19 2019-06-17 2019-06-21 121
13 2019-06-18 18 2019-06-17 2019-06-21 121
您可以进一步删除 2 列 wk start
wk end
并将列 date
设置为索引:
df_out = df_out.drop(['wk start', 'wk end'], axis=1).set_index('date')
结果:
print(df_out)
age height
date
2019-06-10 20 120
2019-06-11 21 120
2019-06-17 19 121
2019-06-18 18 121
笛卡尔积通常很快(如果数据不是那么大),但也会消耗大量内存(在某些情况下效率很低);另一种选择是 intervalIndex :
interval_index = pd.IntervalIndex.from_tuples([*zip(df2['wk start'], df2['wk end'])])
index_position = interval_index.get_indexer(df1.index)
df1.assign(statistic = df2.height[index_position].array)
age statistic
date
2019-06-10 20 120
2019-06-11 21 120
2019-06-17 19 121
2019-06-18 18 121
情况: 我有两个数据框 df1 和 df2,其中 df1 有一个基于天的日期时间索引,df2 有两个日期列 'wk start' 和 'wk end' 是每周范围以及一个数据列 'statistic'存储对应于周范围的数据。
我想做的事情: 在 df1 中添加 'statistic' 的列,由此我查找每个日期(每天,即每一行)并尝试根据该日期所在的星期找到相应的 'statistic'。
我认为答案需要将 df2 合并到 df1 中,但我不知道之后如何进行。
感谢您提供的任何帮助!谢谢!
df1:(注意:我跳过了 2019-06-12 和 2019-06-16 之间的行以保持示例简短。)
年龄 | |
---|---|
日期 | |
2019-06-10 | 20 |
2019-06-11 | 21 |
2019-06-17 | 19 |
2019-06-18 | 18 |
df2:
周开始 | 周结束 | 统计数据 |
---|---|---|
2019-06-10 | 2019-06-14 | 102 |
2019-06-17 | 2019-06-21 | 100 |
2019-06-24 | 2019-06-28 | 547 |
2019-07-02 | 2019-07-25 | 268 |
期望的输出:
年龄 | 统计数据 | |
---|---|---|
日期 | :--- | :-------- |
2019-06-10 | 20 | 102 |
2019-06-11 | 21 | 102 |
2019-06-17 | 19 | 100 |
2019-06-18 | 18 | 100 |
数据帧 d1 和 d2 的代码
import pandas as pd
import datetime
data1 = {'date': ['2019-06-10', '2019-06-11', '2019-06-17', '2019-06-18'], 'age': [20, 21, 19, 18]}
data1['date']=pd.to_datetime(data1['date'])
df1 = pd.DataFrame(data1)
df1.set_index('date', inplace=True)
data2 = {'wk start': ['2019-06-10', '2019-06-17', '2019-06-24', '2019-07-02'], 'wk end':[ '2019-06-14', '2019-06-21', '2019-06-28', '2019-07-05'], 'height': [120,121, 119, 118]}
data2['wk start']=pd.to_datetime(data2['wk start'])
data2['wk end']=pd.to_datetime(data2['wk end'])
df2 = pd.DataFrame(data2)
您可以循环遍历数据帧并在进行时对第二个数据帧进行子集化。
import pandas as pd
import datetime
data1 = {'date': ['2019-06-10', '2019-06-11', '2019-06-17', '2019-06-18'], 'age': [20, 21, 19, 18]}
data1['date']=pd.to_datetime(data1['date'])
df1 = pd.DataFrame(data1)
df1.set_index('date', inplace=True)
data2 = {'wk start': ['2019-06-10', '2019-06-17', '2019-06-24', '2019-07-02'], 'wk end':[ '2019-06-14', '2019-06-21', '2019-06-28', '2019-07-05'], 'height': [120,121, 119, 118]}
data2['wk start']=pd.to_datetime(data2['wk start'])
data2['wk end']=pd.to_datetime(data2['wk end'])
df2 = pd.DataFrame(data2)
# Loop
list1 = []
for row in df1.iterrows():
subdf = df2[(df2['wk start'] <= index) & (df2['wk end'] >= index)]
list1.append(subdf['height'].tolist()[0])
df1['height'] = list1
print(df1)
这些值与您上面显示的table(统计值)有点不同,因为您提供的代码具有不同的值和高度而不是统计值,但原理是相同的。
df[df.some_date.between(start_date, end_date)]
你可以像这样在日期列上使用 isin 方法
df[df[“日期”].isin(pd.date_range(start_date, end_date))]
按照这个
您可以先reset_index()
on df1
to get the date
row index back to data column. Then, cross join df1
and df2
by .merge()
with how='cross'
and then filter the result by date
field is between wk start
and wk end
using .between()
,如下;
df_merge = df1.reset_index().merge(df2, how='cross')
df_out = df_merge[df_merge['date'].between(df_merge['wk start'], df_merge['wk end'])]
或者,如果您的 Pandas 版本小于 1.2.0(2020 年 12 月发布)
df_merge = df1.reset_index().assign(key=1).merge(df2.assign(key=1), on='key').drop('key', axis=1)
df_out = df_merge[df_merge['date'].between(df_merge['wk start'], df_merge['wk end'])]
结果:
print(df_out)
date age wk start wk end height
0 2019-06-10 20 2019-06-10 2019-06-14 120
4 2019-06-11 21 2019-06-10 2019-06-14 120
9 2019-06-17 19 2019-06-17 2019-06-21 121
13 2019-06-18 18 2019-06-17 2019-06-21 121
您可以进一步删除 2 列 wk start
wk end
并将列 date
设置为索引:
df_out = df_out.drop(['wk start', 'wk end'], axis=1).set_index('date')
结果:
print(df_out)
age height
date
2019-06-10 20 120
2019-06-11 21 120
2019-06-17 19 121
2019-06-18 18 121
笛卡尔积通常很快(如果数据不是那么大),但也会消耗大量内存(在某些情况下效率很低);另一种选择是 intervalIndex :
interval_index = pd.IntervalIndex.from_tuples([*zip(df2['wk start'], df2['wk end'])])
index_position = interval_index.get_indexer(df1.index)
df1.assign(statistic = df2.height[index_position].array)
age statistic
date
2019-06-10 20 120
2019-06-11 21 120
2019-06-17 19 121
2019-06-18 18 121