Pandas повторяющихся строк на основе элементов списка - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть pd.Series пунктов списка. Я определяю два местоположения, которые будут дубликатами, если они имеют один или несколько общих элементов списка. Это определение должно быть транзитивным , что означает, что если местоположения A и B являются дубликатами, а местоположения B и C являются дубликатами, то местоположения A и C являются дубликатами.

Примеры:


In [117]: df
Out[117]: 
        A  dupe_group_ix
0  [A, B]              0
1  [D, X]              0
2     [B]              0
3  [D, A]              0
4     [A]              0

Все строки являются дубликатами. Обратите внимание, что строки 0 и 1 являются дубликатами, поскольку строки 0 и 3 являются дубликатами, как и строки 1 и 3.


In [125]: df
Out[125]: 
        A  dupe_group_ix
0  [A, B]              0
1  [D, X]              1
2     [B]              0
3  [K, D]              1
4     [A]              0

В этих примерах две отдельные группы дубликатов.

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

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

grp = {'_':-1}
def map_grp_id(x):
    grp_id = np.max([grp.get(e, -1) for e in x])
    if grp_id < 0:
        grp_id = max(grp.values())+1
        grp.update({e:grp_id for e in x})
    return grp_id

df['dupe_group_ix'] = df.A.apply(map_grp_id)

    A       dupe_group_ix
0   [A, B]              0
1   [D, X]              1
2   [B]                 0
3   [D, K]              1
4   [A]                 0
0 голосов
/ 09 апреля 2020

Улучшенная версия ответа @ Аллена, намного более быстрая (150 мс против 1 мин 46 с c) и позволяющая использовать nans и пустые столбцы.

        grp = {}

        def map_grp_id(x):
            for e in x:
                grp_id = grp.get(e, None)
                if grp_id is not None:
                    return grp_id
            grp_id = len(grp)
            grp.update({e: grp_id for e in x})
            return grp_id

        df.loc[df['A'].map(len, na_action='ignore').eq(0), 'A'] = pd.NA
        df['dupe_group_ix'] = pd.NA
        df['dupe_group_ix'] = df['dupe_group_ix'].astype(pd.Int64Dtype())
        df['dupe_group_ix'] = df[A].map(map_grp_id, na_action='ignore')
...