我们如何提取数据帧中具有连续值的行



我只想选择具有三个或更多连续值的行。

num4<1th>num5<2th>num6>td>45//tr>>11<23>24
num1 num2 num3
1 2 36
3 7 8 910
9 13 21 2224
5 8 11 17 21

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获取每行的差分,比较1DataFrame.eq,通过sum计数Trues,并通过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)]

最新更新