Отбросить повторяющиеся элементы списка в столбец списков - PullRequest
6 голосов
/ 13 июля 2020

Это мой фрейм данных:

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]]})

Ответы [ 4 ]

7 голосов
/ 13 июля 2020

Если вы используете 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 в комментариях, если мы этого не сделаем необходимо сохранить порядок, мы могли бы go с 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
)

введите описание изображения здесь

6 голосов
/ 13 июля 2020

если порядок не имеет значения, вы можете преобразовать столбец в массив numpy и применить операцию к каждой строке в понимании списка.

import numpy as np
df['C_Unique'] = [np.unique(item) for item in df['C'].values]

print(df)

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

Другой метод - использовать explode и groupby.unique

df['CExplode'] = df['C'].explode().groupby(level=0).unique()

  A  B             C      C_Unique      CExplode
0  1  0        [1, 4]        [1, 4]        [1, 4]
1  3  2        [1, 4]        [1, 4]        [1, 4]
2  3  3     [3, 4, 5]     [3, 4, 5]     [3, 4, 5]
3  4  4     [3, 4, 5]     [3, 4, 5]     [3, 4, 5]
4  5  5     [4, 2, 1]     [1, 2, 4]     [4, 2, 1]
5  3  6  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]
6  3  7  [7, 8, 9, 1]  [1, 7, 8, 9]  [7, 8, 9, 1]
3 голосов
/ 13 июля 2020

Вы можете использовать функцию применения в pandas.

df['C'] = df['C'].apply(lambda x: list(set(x)))
2 голосов
/ 13 июля 2020

map и factorize

Давайте добавим еще один.

df['C'].map(pd.factorize).str[1]

0          [1, 4]
1          [1, 4]
2       [3, 4, 5]
3       [3, 4, 5]
4       [4, 2, 1]
5    [1, 2, 3, 4]
6    [7, 8, 9, 1]
Name: C, dtype: object

Или

df['C'].map(lambda x: pd.factorize(x)[1])

0          [1, 4]
1          [1, 4]
2       [3, 4, 5]
3       [3, 4, 5]
4       [4, 2, 1]
5    [1, 2, 3, 4]
6    [7, 8, 9, 1]
Name: C, dtype: object
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...