Pandas 从时间间隔内最后 N 行的第二个数据帧中获取平均值
Pandas get average from second dataframe of the last N rows within time interval
我有2个DF:
DF1
Name
Timestamp
Value
object 1
2021-11-01 10:00:00
1.
object 1
2021-11-01 11:00:00
1.5
object 2
2021-11-01 10:30:00
1.7
DF2
Name
Timestamp
feature
object 1
2021-11-01 8:00:00
0.9
object 1
2021-11-01 9:00:00
1.1
object 1
2021-11-01 9:30:00
1.3
object 1
2021-11-01 12:00:00
1.
object 2
2021-11-01 10:00:00
1.3
object 2
2021-11-01 11:30:00
1.9
DF1 的每一行,我想从 DF2 获得具有相同 Name
且 Timestamp
小于我正在考虑的行的最后 N 行的滚动平均值。 (在本例中假设 N=2)
示例输出应如下所示:
Name
Timestamp
Value
AVG of feature
object 1
2021-11-01 10:00:00
1.
(1.1 + 1.3)/2
object 1
2021-11-01 11:00:00
1.5
(1.1 + 1.3)/2
object 2
2021-11-01 10:30:00
1.7
1.3
理想情况下,我可以根据时差进行加权平均。例如
Name
Timestamp
Value
AVG of feature
object 1
2021-11-01 10:00:00
1.
(60min * 1.1 + 30min * 1.3)/(2 * 90min)
object 1
2021-11-01 11:00:00
1.5
(120min * 1.1 + 90min * 1.3)/(2 * 210min)
object 2
2021-11-01 10:30:00
1.7
1.3
重要提示:我的问题是执行 DF1.apply
会花费很长时间,因为我有大数据帧(DF1 大约是 DF2 的两倍)。我认为最重要的瓶颈在于如何在 DF2 中找到小于 DF1
中当前行的最大时间戳
您需要使用pandas.merge_asof
对齐时间戳:
df1.join(pd
.merge_asof(df2.sort_values(by='Timestamp'),
df1.sort_values(by='Timestamp')
.reset_index()
.drop(columns='Value')
.rename(columns={'Timestamp': 'TS'}),
by='Name', left_on='Timestamp', right_on='TS',
direction='forward')
.assign(weight=lambda d: d['TS'].sub(d['Timestamp']).dt.total_seconds(),
feature=lambda d: d['feature'].mul(d['weight'])
)
.groupby('index').apply(lambda g: g['feature'].sum()/g['weight'].sum()/len(g))
.rename('AVG of (feature)')
)
输出:
Name Timestamp Value AVG of (feature)
0.0 object 1 2021-11-01 10:00:00 1.0 0.583333
1.0 object 1 2021-11-01 11:00:00 1.5 NaN
2.0 object 2 2021-11-01 10:30:00 1.7 1.300000
注意。如果你想传播 AVG 的先前值,你可以使用 ffill
每组
我有2个DF:
DF1
Name | Timestamp | Value |
---|---|---|
object 1 | 2021-11-01 10:00:00 | 1. |
object 1 | 2021-11-01 11:00:00 | 1.5 |
object 2 | 2021-11-01 10:30:00 | 1.7 |
DF2
Name | Timestamp | feature |
---|---|---|
object 1 | 2021-11-01 8:00:00 | 0.9 |
object 1 | 2021-11-01 9:00:00 | 1.1 |
object 1 | 2021-11-01 9:30:00 | 1.3 |
object 1 | 2021-11-01 12:00:00 | 1. |
object 2 | 2021-11-01 10:00:00 | 1.3 |
object 2 | 2021-11-01 11:30:00 | 1.9 |
DF1 的每一行,我想从 DF2 获得具有相同 Name
且 Timestamp
小于我正在考虑的行的最后 N 行的滚动平均值。 (在本例中假设 N=2)
示例输出应如下所示:
Name | Timestamp | Value | AVG of feature |
---|---|---|---|
object 1 | 2021-11-01 10:00:00 | 1. | (1.1 + 1.3)/2 |
object 1 | 2021-11-01 11:00:00 | 1.5 | (1.1 + 1.3)/2 |
object 2 | 2021-11-01 10:30:00 | 1.7 | 1.3 |
理想情况下,我可以根据时差进行加权平均。例如
Name | Timestamp | Value | AVG of feature |
---|---|---|---|
object 1 | 2021-11-01 10:00:00 | 1. | (60min * 1.1 + 30min * 1.3)/(2 * 90min) |
object 1 | 2021-11-01 11:00:00 | 1.5 | (120min * 1.1 + 90min * 1.3)/(2 * 210min) |
object 2 | 2021-11-01 10:30:00 | 1.7 | 1.3 |
重要提示:我的问题是执行 DF1.apply
会花费很长时间,因为我有大数据帧(DF1 大约是 DF2 的两倍)。我认为最重要的瓶颈在于如何在 DF2 中找到小于 DF1
您需要使用pandas.merge_asof
对齐时间戳:
df1.join(pd
.merge_asof(df2.sort_values(by='Timestamp'),
df1.sort_values(by='Timestamp')
.reset_index()
.drop(columns='Value')
.rename(columns={'Timestamp': 'TS'}),
by='Name', left_on='Timestamp', right_on='TS',
direction='forward')
.assign(weight=lambda d: d['TS'].sub(d['Timestamp']).dt.total_seconds(),
feature=lambda d: d['feature'].mul(d['weight'])
)
.groupby('index').apply(lambda g: g['feature'].sum()/g['weight'].sum()/len(g))
.rename('AVG of (feature)')
)
输出:
Name Timestamp Value AVG of (feature)
0.0 object 1 2021-11-01 10:00:00 1.0 0.583333
1.0 object 1 2021-11-01 11:00:00 1.5 NaN
2.0 object 2 2021-11-01 10:30:00 1.7 1.300000
注意。如果你想传播 AVG 的先前值,你可以使用 ffill
每组