pandas 是否有有效的方法来获取带有条件的尾行

is there efficient way for pandas to get tail rows with a condition

我想获取带有条件的尾行

例如: 我想从列 'A' 中获取所有负尾行,例如:

    test = pd.DataFrame({'A':[-8, -9, -10, 1, 2, 3, 0, -1,-2,-3]})

我希望 'method' 获得像这样的新框架:

        A
    0  -1
    1  -2
    2  -3

注意,尾部有多少'negative'个数字是不确定的。所以我不能 运行 test.tail(3)

看起来 pandas 提供的 'tail()' 函数只能 运行 给定的数字。

但是我的输入数据框可能太大了,我不想运行一个简单的循环来一个一个地检查

有没有聪明的方法来做到这一点?

尾巴有什么用?看来你只需要负数

test.query("A < 0")

更新:找到符号变化的地方,拆分数组并选择最后一个

split_points = (test.A.shift(1)<0) == (test.A<0) 
np.split(test, split_points.loc[lambda x: x==False].index.tolist())[-1]

输出:

    A
7   -1
8   -2
9   -3

这是你想要的吗?

test = pd.DataFrame({'A':[-8, -9, -10, 1, 2, 3, 0, -1,-2,-3]})

test = test.iloc[::-1]

test.loc[test.index.max():test[test['A'].ge(0)].index[0]+1]

输出:

    A
9   -3
8   -2
7   -1

编辑,如果你想把它恢复成原来的顺序:

test.loc[test.index.max():test[test['A'].ge(0)].index[0]+1].iloc[::-1]

    A
7   -1
8   -2
9   -3

如果您需要从 0 开始的索引,也可以选择 .reset_index(drop=True)

只需分享一张比较以上两个给定答案的性能图片 感谢 Patry 和 Macro

我改进了上面的测试,又做了一轮测试,因为我觉得旧的'testing sample'尺寸太小了,担心%%time测量可能不准确。

我的新测试使用了一个非常大的头部数字,大小为 10000000,尾部有 3 个负数

因此新测试可以证明整个数据帧大小如何影响整体性能。

代码如下:

    %%time
    arr = np.arange(1,10000000,1)
    arr = np.concatenate((arr, [-2,-3,-4]))
    test = pd.DataFrame({'A':arr})
    test = test.iloc[::-1]
    test.loc[test.index.max():test[test['A'].ge(0)].index[0]+1].iloc[::-1]
    %%time
    arr = np.arange(1,10000000,1)
    arr = np.concatenate((arr, [-2,-3,-4]))
    test = pd.DataFrame({'A':arr})
    split_points = (test.A.shift(1)<0) == (test.A<0) 
    np.split(test, split_points.loc[lambda x: x==False].index.tolist())[-1]

由于系统影响,我测试了10次,以上2种方法执行起来非常相似。在大约 50% 的情况下,Patryk 的代码甚至执行得更快

查看下面这张图片