我有两个熊猫时间序列数据帧,我想基于另一个时间间隔的时间值来汇总一个时间序列的值。让我以身作则。 第一次时间序列如下:
date value
0 2016-03-21 10
1 2016-03-25 10
2 2016-04-10 10
3 2016-05-05 10
第二个是从上述系列中提取的间隔为10个日历日的日期范围。我已经编写了从上述数据中提取代码的代码。
date
0 2016-03-21
1 2016-03-31
2 2016-04-10
3 2016-04-20
4 2016-04-30
我想编写一些代码来获得结果数据框:
date value
0 2016-03-21 20
1 2016-03-31 0
2 2016-04-10 10
3 2016-04-20 0
4 2016-04-30 10
请提出一种无需在python中使用循环(最好是使用循环)的方法吗?
答案 0 :(得分:5)
您可以根据df2日期中的bin对df1中的数据进行分类,
bins = pd.date_range(df2.date.min(), df2.date.max() + pd.DateOffset(10), freq = '10D')
labels = df2.date
df1.groupby(pd.cut(df1.date, bins = bins, right = False, labels = labels)).value.sum().reset_index()
date value
0 2016-03-21 20
1 2016-03-31 0
2 2016-04-10 10
3 2016-04-20 0
4 2016-04-30 10
答案 1 :(得分:4)
searchsorted
这是我想到的第一件事,但解决起来并不容易。 @Vaishali的回答在本质上与此相似并且更为简单。但是我就像一条有骨头的狗,要弄清楚它,我才能放手。
解释一下。 searchsorted
将遍历一个数组,在这种情况下,它们是等距的日期,并找到它们将放置在另一个数组中的位置,以保持排序。这听起来很复杂,但是如果我们可视化,我们可以看到发生了什么。我将用字母进行演示。我将选择与日期相对应的字母。
x = np.array([*'abdg'])
y = np.array([*'acdef'])
请注意,对于x
中的每个字母,我都找到了y
中支持者的位置
# i -> 0 0 2 4
# x -> a b d g
# y -> a c d e f
这符合我在下面所做的事情。
df = pd.DataFrame(dict(
date=pd.to_datetime(['2016-03-21', '2016-03-25', '2016-04-10', '2016-05-05']),
value=[10, 10, 10, 10]
))
dates = pd.date_range(df.date.min(), df.date.max(), freq='10D')
d = df.date.values
v = df.value.values
i = dates.searchsorted(d, side='right') - 1
a = np.zeros(len(dates), dtype=v.dtype)
np.add.at(a, i, v)
pd.DataFrame(dict(
date=dates, value=a
))
date value
0 2016-03-21 20
1 2016-03-31 0
2 2016-04-10 10
3 2016-04-20 0
4 2016-04-30 10
您会注意到,我使用np.add.at
是为了在正确的位置求和v
。我也可以使用np.bincount
完成此操作。我更喜欢上面的方法,因为即使np.bincount
的类型为float
,v
也会强制转换为int
。
d = df.date.values
v = df.value.values
i = dates.searchsorted(d, side='right') - 1
pd.DataFrame(dict(
date=dates, value=np.bincount(i, v).astype(v.dtype)
))
date value
0 2016-03-21 20
1 2016-03-31 0
2 2016-04-10 10
3 2016-04-20 0
4 2016-04-30 10
答案 2 :(得分:3)
只要有时间添加我的解决方案,numpy
广播
s1=df1.date.values
s2=df2.date.values
a=(np.abs(s1-s2[:,None])/np.timedelta64(60*60*24, 's')<10).dot(df1.value.values)
a
Out[183]: array([20, 10, 10, 0, 10], dtype=int64)
#df2['value']=a