首页 > 解决方案 > Pandas 使用先前的排名值过滤掉当前行

问题描述

正如标题所述,我正在尝试使用以前的排名来过滤掉当前的排名

这是我开始 df 的示例

df = pd.DataFrame({
    'rank': [1, 1, 2, 2, 3, 3],
    'x': [0, 3, 0, 3, 4, 2],
    'y': [0, 4, 0, 4, 5, 5],
    'z': [1, 3, 1.2, 2.95, 3, 6],
})
print(df)
#    rank  x  y     z
# 0     1  0  0  1.00
# 1     1  3  4  3.00
# 2     2  0  0  1.20
# 3     2  3  4  2.95
# 4     3  4  5  3.00
# 5     3  2  5  6.00

这就是我想要的输出

output = pd.DataFrame({
    'rank': [1, 1, 2, 3],
    'x': [0, 3, 0, 2],
    'y': [0, 4, 0, 5],
    'z': [1, 3, 1.2, 6],
})
print(output)
#    rank  x  y    z
# 0     1  0  0  1.0
# 1     1  3  4  3.0
# 2     2  0  0  1.2
# 5     3  2  5  6.00

基本上我想要发生的是,如果前一个等级有任何带有 x, y (+- 1 双向) 和 z (+- .1) 的行来删除它。

因此,对于排名 1 的行,排名 2 中的任意行具有 x = (-1-1)、y = (-1-1)、z= (.9-1.1) 或 x = (2-5) 的任意组合, y = (3-5), z= (2.9-3.1) 我希望它被删除

提前感谢所有帮助!

标签: pythonpython-3.xpandas

解决方案


这有点棘手,因为您需要访问前一个组。您可以先使用计算组groupby,然后遍历元素并使用自定义函数执行检查:

def check_previous_group(rank, d, groups):
    if not rank-1 in groups.groups:
        # check is a previous group exists, else flag all rows False (i.e. not to be dropped)
        return pd.Series(False, index=d1.index)

    else:
        # get previous group (rank-1)
        d_prev = groups.get_group(rank-1)

        # get the absolute difference per row with the whole dataset 
        # of the previous group: abs(d_prev-s)
        # if all differences are within 1/1/0.1 for x/y/z
        # for at least one rows of the previous group
        # then flag the row to be dropped (True)
        return d.apply(lambda s: abs(d_prev-s)[['x', 'y', 'z']].le([1,1,0.1]).all(1).any(), axis=1)

groups = df.groupby('rank')
mask = pd.concat([check_previous_group(rank, d, groups) for rank,d in groups])
df[~mask]

输出:

   rank  x  y    z
0     1  0  0  1.0
1     1  3  4  3.0
2     2  0  0  1.2
5     3  2  5  6.0

推荐阅读