根据时间戳间隔重叠乘以数据帧
multiply dataframes based on timestamp intervals overlap
我有两个 pandas 数据帧,每个数据帧都有两列:测量值和时间戳。我需要乘以测量的一阶差分,但前提是两个测量间隔之间存在时间重叠。随着数据帧的大小变大,我怎样才能有效地做到这一点?
示例:
dfA
mesA timeA
0 125 2015-01-14 04:44:49
1 100 2015-01-14 05:16:23
2 115 2015-01-14 08:57:10
dfB
mesB timeB
0 140 2015-01-14 00:13:17
1 145 2015-01-14 08:52:01
2 120 2015-01-14 11:31:44
这里我会乘以 (100-125)*(145-140)
,因为 [04:44:49, 05:16:23]
和 [00:13:17, 08:52:01]
之间存在时间重叠,但 (100-125)
和 (120-145)
之间没有时间重叠,因为没有一个。同样,我会有 (115-100)*(145-140)
,但也会有 (115-100)*(120-145)
,因为两者都有时间重叠。
最后我必须将所有相关产品汇总到一个值中,因此结果不必是数据框。在这种情况下:
s = (100-125)*(145-140)+(115-100)*(145-140)+(115-100)*(120-145) = -425
我目前的解决方案:
s = 0
for i in range(1, len(dfA)):
startA = dfA['timeA'][i-1]
endA = dfA['timeA'][i]
for j in range(1, len(dfB)):
startB = dfB['timeB'][j-1]
endB = dfB['timeB'][j]
if (endB>startA) & (startB<endA):
s+=(dfA['mesA'][i]-dfA['mesA'][i-1])*(dfB['mesB'][j]-dfB['mesB'][j-1])
虽然它似乎有效,但它非常低效并且对于非常大的数据集变得不切实际。我相信它可以更有效地矢量化,也许使用 numexpr
,但我仍然没有找到方法。
编辑:
其他数据
mesA timeA
0 125 2015-01-14 05:54:03
1 100 2015-01-14 11:39:53
2 115 2015-01-14 23:58:13
mesB timeB
0 110 2015-01-14 10:58:32
1 120 2015-01-14 13:30:00
2 135 2015-01-14 22:29:26
s = 125
编辑:原来的答案没有用,所以我想出了另一个没有矢量化但需要按日期排序的版本。
arrA = dfA.timeA.to_numpy()
startA, endA = arrA[0], arrA[1]
arr_mesA = dfA.mesA.diff().to_numpy()
mesA = arr_mesA[1]
arrB = dfB.timeB.to_numpy()
startB, endB = arrB[0], arrB[1]
arr_mesB = dfB.mesB.diff().to_numpy()
mesB = arr_mesB[1]
s = 0
i, j = 1, 1
imax = len(dfA)-1
jmax = len(dfB)-1
while True:
if (endB>startA) & (startB<endA):
s+=mesA*mesB
if (endB>endA) and (i<imax):
i+=1
startA, endA, mesA= endA, arrA[i], arr_mesA[i]
elif j<jmax:
j+=1
startB, endB, mesB = endB, arrB[j], arr_mesB[j]
else:
break
原始答案无效
我们的想法是根据两个数据框中 dfB['timeB']
中的值对 pd.cut
进行分类,以查看它们可能重叠的位置。然后计算测量中的 diff
。 merge
类别上的两个数据框,最后相乘 sum
整个事情
# create bins
bins_dates = [min(dfB['timeB'].min(), dfA['timeA'].min())-pd.DateOffset(hours=1)]\
+ dfB['timeB'].tolist()\
+ [max(dfB['timeB'].max(), dfA['timeA'].max())+pd.DateOffset(hours=1)]
# work on dfB
dfB['cat'] = pd.cut(dfB['timeB'], bins=bins_dates,
labels=range(len(bins_dates)-1), right=False)
dfB['deltaB'] = -dfB['mesB'].diff(-1).ffill()
# work on dfA
dfA['cat'] = pd.cut(dfA['timeA'], bins=bins_dates,
labels=range(len(bins_dates)-1), right=False)
# need to calcualte delta for both start and end of intervals
dfA['deltaAStart'] = -dfA['mesA'].diff(-1)
dfA['deltaAEnd'] = dfA['mesA'].diff().mask(dfA['cat'].astype(float).diff().eq(0))
# in the above method, for the end of interval, use a mask to not count twice
# intervals that are fully included in one interval of B
# then merge and calcualte the multiplication you are after
df_ = dfB[['cat', 'deltaB']].merge(dfA[['cat','deltaAStart', 'deltaAEnd']])
s = (df_['deltaB'].to_numpy()[:,None]*df_[['deltaAStart', 'deltaAEnd']]).sum().sum()
print (s)
#-425.0
我有两个 pandas 数据帧,每个数据帧都有两列:测量值和时间戳。我需要乘以测量的一阶差分,但前提是两个测量间隔之间存在时间重叠。随着数据帧的大小变大,我怎样才能有效地做到这一点? 示例:
dfA
mesA timeA
0 125 2015-01-14 04:44:49
1 100 2015-01-14 05:16:23
2 115 2015-01-14 08:57:10
dfB
mesB timeB
0 140 2015-01-14 00:13:17
1 145 2015-01-14 08:52:01
2 120 2015-01-14 11:31:44
这里我会乘以 (100-125)*(145-140)
,因为 [04:44:49, 05:16:23]
和 [00:13:17, 08:52:01]
之间存在时间重叠,但 (100-125)
和 (120-145)
之间没有时间重叠,因为没有一个。同样,我会有 (115-100)*(145-140)
,但也会有 (115-100)*(120-145)
,因为两者都有时间重叠。
最后我必须将所有相关产品汇总到一个值中,因此结果不必是数据框。在这种情况下:
s = (100-125)*(145-140)+(115-100)*(145-140)+(115-100)*(120-145) = -425
我目前的解决方案:
s = 0
for i in range(1, len(dfA)):
startA = dfA['timeA'][i-1]
endA = dfA['timeA'][i]
for j in range(1, len(dfB)):
startB = dfB['timeB'][j-1]
endB = dfB['timeB'][j]
if (endB>startA) & (startB<endA):
s+=(dfA['mesA'][i]-dfA['mesA'][i-1])*(dfB['mesB'][j]-dfB['mesB'][j-1])
虽然它似乎有效,但它非常低效并且对于非常大的数据集变得不切实际。我相信它可以更有效地矢量化,也许使用 numexpr
,但我仍然没有找到方法。
编辑: 其他数据
mesA timeA
0 125 2015-01-14 05:54:03
1 100 2015-01-14 11:39:53
2 115 2015-01-14 23:58:13
mesB timeB
0 110 2015-01-14 10:58:32
1 120 2015-01-14 13:30:00
2 135 2015-01-14 22:29:26
s = 125
编辑:原来的答案没有用,所以我想出了另一个没有矢量化但需要按日期排序的版本。
arrA = dfA.timeA.to_numpy()
startA, endA = arrA[0], arrA[1]
arr_mesA = dfA.mesA.diff().to_numpy()
mesA = arr_mesA[1]
arrB = dfB.timeB.to_numpy()
startB, endB = arrB[0], arrB[1]
arr_mesB = dfB.mesB.diff().to_numpy()
mesB = arr_mesB[1]
s = 0
i, j = 1, 1
imax = len(dfA)-1
jmax = len(dfB)-1
while True:
if (endB>startA) & (startB<endA):
s+=mesA*mesB
if (endB>endA) and (i<imax):
i+=1
startA, endA, mesA= endA, arrA[i], arr_mesA[i]
elif j<jmax:
j+=1
startB, endB, mesB = endB, arrB[j], arr_mesB[j]
else:
break
原始答案无效
我们的想法是根据两个数据框中 dfB['timeB']
中的值对 pd.cut
进行分类,以查看它们可能重叠的位置。然后计算测量中的 diff
。 merge
类别上的两个数据框,最后相乘 sum
整个事情
# create bins
bins_dates = [min(dfB['timeB'].min(), dfA['timeA'].min())-pd.DateOffset(hours=1)]\
+ dfB['timeB'].tolist()\
+ [max(dfB['timeB'].max(), dfA['timeA'].max())+pd.DateOffset(hours=1)]
# work on dfB
dfB['cat'] = pd.cut(dfB['timeB'], bins=bins_dates,
labels=range(len(bins_dates)-1), right=False)
dfB['deltaB'] = -dfB['mesB'].diff(-1).ffill()
# work on dfA
dfA['cat'] = pd.cut(dfA['timeA'], bins=bins_dates,
labels=range(len(bins_dates)-1), right=False)
# need to calcualte delta for both start and end of intervals
dfA['deltaAStart'] = -dfA['mesA'].diff(-1)
dfA['deltaAEnd'] = dfA['mesA'].diff().mask(dfA['cat'].astype(float).diff().eq(0))
# in the above method, for the end of interval, use a mask to not count twice
# intervals that are fully included in one interval of B
# then merge and calcualte the multiplication you are after
df_ = dfB[['cat', 'deltaB']].merge(dfA[['cat','deltaAStart', 'deltaAEnd']])
s = (df_['deltaB'].to_numpy()[:,None]*df_[['deltaAStart', 'deltaAEnd']]).sum().sum()
print (s)
#-425.0