首页 > 解决方案 > 删除列表列中的重复列表元素

问题描述

这是我的数据框:

pd.DataFrame({'A':[1, 3, 3, 4, 5, 3, 3],
              'B':[0, 2, 3, 4, 5, 6, 7],
              'C':[[1,4,4,4], [1,4,4,4], [3,4,4,5], [3,4,4,5], [4,4,2,1], [1,2,3,4,], [7,8,9,1]]})

我想设置\删除每行 C 列的重复值,但不删除重复的行。

这是我希望得到的:

pd.DataFrame({'A':[1, 3, 3, 4, 5, 3, 3],
              'B':[0, 2, 3, 4, 5, 6, 7],
              'C':[[1,4], [1,4], [3,4,5], [3,4,5], [4,2,1], [1,2,3,4,], [7,8,9,1]]})

标签: pythonpandassetdrop-duplicates

解决方案


如果您使用的是 python 3.7>,则可以map使用dict.fromkeys, 并从字典键中获取列表(版本相关,因为从那里开始维护插入顺序):

df['C'] = df.C.map(lambda x: list(dict.fromkeys(x).keys()))

对于较旧的蟒蛇,您有collections.OrderedDict

from collections import OrderedDict
df['c']= df.C.map(lambda x: list(OrderedDict.fromkeys(x).keys()))

print(df)

   A  B             C
0  1  0        [1, 4]
1  3  2        [1, 4]
2  3  3     [3, 4, 5]
3  4  4     [3, 4, 5]
4  5  5     [4, 2, 1]
5  3  6  [1, 2, 3, 4]
6  3  7  [7, 8, 9, 1]

正如 cs95 在评论中提到的,如果我们不需要保留顺序,我们可以采用set更简洁的方法:

df['c'] = df.C.map(lambda x: [*{*x}])

由于已经提出了几种方法并且很难判断它们将如何在大型数据帧上执行,因此可能值得进行基准测试:

df = pd.concat([df]*50000, axis=0).reset_index(drop=True)

perfplot.show(
    setup=lambda n: df.iloc[:int(n)], 

    kernels=[
        lambda df: df.C.map(lambda x: list(dict.fromkeys(x).keys())),
        lambda df: df['C'].map(lambda x: pd.factorize(x)[1]),
        lambda df: [np.unique(item) for item in df['C'].values],
        lambda df: df['C'].explode().groupby(level=0).unique(),
        lambda df: df.C.map(lambda x: [*{*x}]),
    ],

    labels=['dict.from_keys', 'factorize', 'np.unique', 'explode', 'set'],
    n_range=[2**k for k in range(0, 18)],
    xlabel='N',
    equality_check=None
)

在此处输入图像描述


推荐阅读