我只想选择具有三个或更多连续值的行。
num1 | num2 | num3 | num4<1th>num5<2th>num6||
---|---|---|---|---|
1 | 2 | 3 | >td>456 | //tr>|
3 | 7 | 8 | 9 | >10 | 11
9 | 13 | 21 | 22 | <23>24 |
5 | 8 | 11 | 17 | 21 | 24
IIUC,计算列上的diff
,选择等于1的值(即连续值((使用eq
(,并确定是否有任何3个具有rolling.sum
的连续值。使用生成的系列执行布尔索引:
N=3
df[df.diff(axis=1).eq(1).T.rolling(window=N).sum().ge(N).any()]
输出:
num1 num2 num3 num4 num5 num6
0 1 2 3 4 5 6
1 3 7 8 9 10 11
2 9 13 21 22 23 24
连续值的中间计数:
>>> df.diff(axis=1).eq(1).T.rolling(window=3).sum()
0 1 2 3
num1 NaN NaN NaN NaN
num2 NaN NaN NaN NaN
num3 2.0 1.0 0.0 0.0
num4 3.0 2.0 1.0 0.0
num5 3.0 3.0 2.0 0.0
num6 3.0 3.0 3.0 0.0
以前的错误答案(本问答中的每个人都常见(
这只是计算连续值的数量,而不是如果它们都是连续的。例如1-2-4-5-7-8将计数3个连续的,而它们并非全部连续*
N = 3
df1 = df[df.diff(axis=1).eq(1).sum(axis=1).ge(N)]
通过DataFrame.diff
获取每行的差分,比较1
和DataFrame.eq
,通过sum
计数True
s,并通过Series.ge
:比较是否大于或等于
df1 = df[df.diff(axis=1).eq(1).sum(axis=1).ge(3)]
编辑:您可以通过cumulative sum
计数差分的连续1
,然后获得最大值并比较是否大于或等于:
print (df)
num1 num2 num3 num4 num5 num6
0 1 2 4 5 8 9
1 3 7 8 9 10 11
2 9 13 21 22 23 24
3 5 8 11 17 21 24
df1 = df.diff(axis=1)
m = df1.eq(1)
b = m.cumsum(axis=1)
mask = b.sub(b.mask(m).ffill(axis=1).fillna(0)).max(axis=1).ge(3)
df2 = df[mask]
print (df2)
num1 num2 num3 num4 num5 num6
1 3 7 8 9 10 11
2 9 13 21 22 23 24
详细信息:
print (b.sub(b.mask(m).ffill(axis=1).fillna(0)))
num1 num2 num3 num4 num5 num6
0 0.0 1.0 0.0 1.0 0.0 1.0
1 0.0 0.0 1.0 2.0 3.0 4.0
2 0.0 0.0 0.0 1.0 2.0 3.0
3 0.0 0.0 0.0 0.0 0.0 0.0
性能(真实数据中的最佳测试(,但通常rolling
在这里是瓶颈:
#40k rows
df = pd.concat([df] * 10000, ignore_index=True)
In [82]: %%timeit
...: df1 = df.diff(axis=1)
...: m = df1.eq(1)
...: b = m.cumsum(axis=1)
...: mask = b.sub(b.mask(m).ffill(axis=1).fillna(0)).max(axis=1).ge(3)
...: df[mask]
...:
...:
35.6 ms ± 475 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [83]: %%timeit
...: df[df.diff(axis=1).eq(1).T.rolling(window=N).sum().ge(N).any()]
...:
2.79 s ± 63.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
试试这个:
df = df[df.diff(axis=1).eq(1).sum(axis=1).ge(3)]