熊猫计算自当前单元格值>以来的行数



我有一个数据帧df:

col_1
0  51.0  
1  52.0  
2  51.5  
3  51.5  
4  53.0  
5  54.0  
6  52.0  
7  53.0  
8  50.5  
9  50.0  
10  52.0  

我想倒计数行数,直到找到一个大于当前值的值,或者直到到达第一行。例如,结果将是:

col_1 count
0  51.0  0
1  52.0  1
2  51.5  0
3  51.5  1
4  53.0  4
5  54.0  5
6  52.0  0
7  53.0  1
8  50.5  0
9  50.0  0
10  52.0  2

我基本上是想在df['col_1'].rolling(n).max()中为级数的每个值找到n的值。我该怎么做?提前谢谢。

numpy approach

a = df['col_1'].values[::-1]
m = np.triu(a[:, None] <  a)
i = m.argmax(1)
i[~m.any(1)] = len(m)
df['count'] = (i - range(len(m)) - 1)[::-1]

它是如何工作的

  • 反转列col_1并获得numpy视图
>>> a
array([52. , 50. , 50.5, 53. , 52. , 54. , 53. , 51.5, 51.5, 52. , 51. ])
  • 使用广播将列a与自身进行比较
>>> a[:, None] <  a
[[False False False  True False  True  True False False False False]
[ True False  True  True  True  True  True  True  True  True  True]
[ True False False  True  True  True  True  True  True  True  True]
[False False False False False  True False False False False False]
[False False False  True False  True  True False False False False]
[False False False False False False False False False False False]
[False False False False False  True False False False False False]
[ True False False  True  True  True  True False False  True False]
[ True False False  True  True  True  True False False  True False]
[False False False  True False  True  True False False False False]
[ True False False  True  True  True  True  True  True  True False]]
  • 使用triu(上三角形(屏蔽主对角线左侧的值,因为我们只关心当前值之后的值。将其视为表示当前值的主对角线
>>> np.triu(a[:, None] < a)
[[False False False  True False  True  True False False False False]
[False False  True  True  True  True  True  True  True  True  True]
[False False False  True  True  True  True  True  True  True  True]
[False False False False False  True False False False False False]
[False False False False False  True  True False False False False]
[False False False False False False False False False False False]
[False False False False False False False False False False False]
[False False False False False False False False False  True False]
[False False False False False False False False False  True False]
[False False False False False False False False False False False]
[False False False False False False False False False False False]]
  • 沿着列轴找到最大值的索引,这表示当前值之后的第一个最大值的指数。若并没有找到最大值,我们就将这些索引更新为级数的长度
>>> i = m.argmax(1)
>>> i[~m.any(1)] = len(m)
>>> i
array([ 3,  2,  3,  5,  5, 11, 11,  9,  9, 11, 11])
  • 以上索引为零,但我们必须计算到主对角线的距离,因此我们可以从主对角线的索引中减去这些索引来计算距离(行数(
>>> df['count'] = (i - range(len(m)) - 1)[::-1]
>>> df
col_1  count
0    51.0      0
1    52.0      1
2    51.5      0
3    51.5      1
4    53.0      4
5    54.0      5
6    52.0      0
7    53.0      1
8    50.5      0
9    50.0      0
10   52.0      2

我想到了这个,它可能不是很有效的方法,但它似乎有效:

dr = df.iloc[::-1,0] # col_1 reversed
dr = dr.reset_index(drop=True)
count = []
for i, v in dr.iteritems():
d = dr.iloc[i:]
try:
ix = d[d > v].index[0] - i 
except IndexError:
ix = len(d)
count.append(ix - 1)
df["count"] = count[::-1]
print(df)

col_1  count
0    51.0      0
1    52.0      1
2    51.5      0
3    51.5      1
4    53.0      4
5    54.0      5
6    52.0      0
7    53.0      1
8    50.5      0
9    50.0      0
10   52.0      2

最新更新