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

mat*_*teo 2 python numpy dataframe pandas

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

数字1 数字2 数字3 数字4 数字5 数字6
1 2 3 4 5 6
3 7 8 9 10 11
9 13 21 22 23 24
5 8 11 17 号 21 24

[结果]

数字1 数字2 数字3 数字4 数字5 数字6
1 2 3 4 5 6
3 7 8 9 10 11
9 13 21 22 23 24

有没有使用 pandas 或 numpy 的简单方法?

jez*_*ael 5

获取每行的差异DataFrame.diff,比较1DataFrame.eq,计数Trues bysum并比较是否大于或等于Series.ge

\n
df1 = df[df.diff(axis=1).eq(1).sum(axis=1).ge(3)]\n
Run Code Online (Sandbox Code Playgroud)\n

编辑:您可以1通过以下方式计算连续的差异cumulative sum,然后获取最大值并比较是否大于或等于:

\n
print (df)\n   num1  num2  num3  num4  num5  num6\n0     1     2     4     5     8     9\n1     3     7     8     9    10    11\n2     9    13    21    22    23    24\n3     5     8    11    17    21    24\n\ndf1 = df.diff(axis=1)\nm = df1.eq(1)\nb = m.cumsum(axis=1)\nmask = b.sub(b.mask(m).ffill(axis=1).fillna(0)).max(axis=1).ge(3)\ndf2 = df[mask]\nprint (df2)\n   num1  num2  num3  num4  num5  num6\n1     3     7     8     9    10    11\n2     9    13    21    22    23    24\n
Run Code Online (Sandbox Code Playgroud)\n

细节

\n
print (b.sub(b.mask(m).ffill(axis=1).fillna(0)))\n   num1  num2  num3  num4  num5  num6\n0   0.0   1.0   0.0   1.0   0.0   1.0\n1   0.0   0.0   1.0   2.0   3.0   4.0\n2   0.0   0.0   0.0   1.0   2.0   3.0\n3   0.0   0.0   0.0   0.0   0.0   0.0\n
Run Code Online (Sandbox Code Playgroud)\n

性能(真实数据中的最佳测试),但一般来说rolling这里是瓶颈:

\n
#40k rows\ndf = pd.concat([df] * 10000, ignore_index=True)\n\nIn [82]: %%timeit\n    ...: df1 = df.diff(axis=1)\n    ...: m = df1.eq(1)\n    ...: b = m.cumsum(axis=1)\n    ...: mask = b.sub(b.mask(m).ffill(axis=1).fillna(0)).max(axis=1).ge(3)\n    ...: df[mask]\n    ...: \n    ...: \n35.6 ms \xc2\xb1 475 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n\n\nIn [83]: %%timeit\n    ...: df[df.diff(axis=1).eq(1).T.rolling(window=N).sum().ge(N).any()]\n    ...: \n2.79 s \xc2\xb1 63.6 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n


moz*_*way 5

IIUC,计算diff列上的 a,选择等于 1 的值(即连续值)(带有eq),并确定是否存在 3 个连续值rolling.sum。使用生成的 Series 执行布尔索引

N=3
df[df.diff(axis=1).eq(1).T.rolling(window=N).sum().ge(N).any()]
Run Code Online (Sandbox Code Playgroud)

输出:

   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
Run Code Online (Sandbox Code Playgroud)

连续值的中间计数:

>>> 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
Run Code Online (Sandbox Code Playgroud)
之前的错误答案(本问答中的每个人都很常见)

这仅计算连续值的数量,而不计算它们是否都是连续的。例如 1-2-4-5-7-8 将算作 3 个连续的,但它们并不都是连续的*

N = 3
df1 = df[df.diff(axis=1).eq(1).sum(axis=1).ge(N)]
Run Code Online (Sandbox Code Playgroud)