2016-11-04 151 views
1

我非常肯定这有一个非常简单的解决方案,我只是没有意识到它。然而...通过另一个数据帧中的值列表拆分熊猫数据帧

我有一个高频数据的数据帧。调用这个数据框A.我还有一个单独的低频率分界点列表,称这个B.我想给A添加一列,如果A的时间戳列在B [0]和B [1 ],2如果它在B [1]和B [2]之间,依此类推。

如上所述,这可能非常微不足道,而我在这一个小时就没有意识到它。

回答

2

这是一个使用列表理解的快速和肮脏的方法。

>>> df = pd.DataFrame({'A': np.arange(1, 3, 0.2)}) 

>>> A = df.A.values.tolist() 
A: [1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.5, 2.6, 2.8] 

>>> B = np.arange(0, 3, 1).tolist() 
B: [0, 1, 2] 

>>> BA = [k for k in range(0, len(B)-1) for a in A if (B[k]<=a) & (B[k+1]>a) or (a>max(B))] 
BA: [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 
2

使用searchsorted

A['group'] = B['timestamp'].searchsorted(A['timestamp']) 

对于A['timestamp']每个值,则返回的索引值。该索引指示B['timestamp']中的排序值中的哪个值将从A插入到B以便维持排序顺序。

例如,

import numpy as np 
import pandas as pd 
np.random.seed(2016) 

N = 10 
A = pd.DataFrame({'timestamp':np.random.uniform(0, 1, size=N).cumsum()}) 
B = pd.DataFrame({'timestamp':np.random.uniform(0, 3, size=N).cumsum()}) 
# timestamp 
# 0 1.739869 
# 1 2.467790 
# 2 2.863659 
# 3 3.295505 
# 4 5.106419 
# 5 6.872791 
# 6 7.080834 
# 7 9.909320 
# 8 11.027117 
# 9 12.383085 

A['group'] = B['timestamp'].searchsorted(A['timestamp']) 
print(A) 

产生

timestamp group 
0 0.896705  0 
1 1.626945  0 
2 2.410220  1 
3 3.151872  3 
4 3.613962  4 
5 4.256528  4 
6 4.481392  4 
7 5.189938  5 
8 5.937064  5 
9 6.562172  5 

因此,时间戳0.896705是在组0因为它是前B['timestamp'][0](即1.739869)。时间戳2.410220在组1中,因为它大于B['timestamp'][0](即1.739869)但小于B['timestamp'][1](即2.467790)。


你也应该决定做什么,如果在A['timestamp']值正好等于在B['timestamp']截止值之一。使用

B['timestamp'].searchsorted(A['timestamp'], side='left') 

,如果你想searchsorted返回iB['timestamp'][i] <= A['timestamp'][i] <= B['timestamp'][i+1]。使用

B['timestamp'].searchsorted(A['timestamp'], side='right') 

如果你想在这种情况下searchsorted返回i+1。如果您未指定side,则默认使用side='left'