如何在Pandas系列中检测行是其他行子集并删除它们

ddhy6vgd  于 2023-02-14  发布在  其他
关注(0)|答案(1)|浏览(123)

我有一个Pandas系列,其中每一行,是一个数字列表。我想检测行是其他行的子集,并删除他们从系列。
我的解决方案是使用2个for循环,但它非常慢。有人能帮我介绍一个更快的方法吗?因为我的for循环非常慢。
例如,在下面的示例中,我们必须删除行2、4,因为它们分别是行1、3的子集。

import pandas as pd

cycles = pd.Series([[1, 2, 3, 4], [3, 4], [5, 6, 9, 7], [5, 9]])
ryevplcw

ryevplcw1#

首先,你可以对列表进行排序,因为它们是数字,并将它们转换为字符串。然后,对于每个字符串,只需检查它是否是任何其他行的子字符串,如果是,它就是子集。由于所有内容都进行了排序,我们可以确保数字的顺序不会影响这一步。
最后,只过滤掉那些没有被标识为子集的。

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'cycles': [[9, 5, 4, 3], [9, 5, 4], [2, 4, 3], [2, 3]],
    'members': [4, 3, 3, 2]
})
print(df)

         cycles  members
0  [9, 5, 4, 3]        4
1     [9, 5, 4]        3
2     [2, 4, 3]        3
3        [2, 3]        2
df['cycles'] = df['cycles'].map(np.sort) 
df['cycles_str'] = [','.join(map(str, c)) for c in df['cycles']]
# Here we check if matches are >1, because it will match with itself once!
df['is_subset'] = [df['cycles_str'].str.contains(c_str).sum() > 1 for c_str in df['cycles_str']]
df = df.loc[df['is_subset'] == False]
df = df.drop(['cycles_str', 'is_subset'], axis=1)

         cycles  members
0  [3, 4, 5, 9]        4
2     [2, 3, 4]        3
    • 编辑-以上操作不适用于[1,2,4]和[1,2,3,4]**

重写了代码。使用2个循环和set检查列表解析的子集:

# check if >1 True, as it will match with itself once!
df['is_subset'] = [[set(y).issubset(set(x)) for x in df['cycles']].count(True)>1 for y in df['cycles']]
df = df.loc[df['is_subset'] == False]
df = df.drop('is_subset', axis=1)
print(df)

         cycles  members
0  [9, 5, 4, 3]        4
2     [2, 4, 3]        3

相关问题