(Панды) удалить дублированные группы, созданные GroupBy - PullRequest
0 голосов
/ 03 декабря 2018

Я хотел бы создать группы с помощью пользовательского идентификатора, а затем исключить группы, которые являются дубликатами в некоторых столбцах.

Например,

| id | A   | B  |
|----|-----|----|
| 1  | foo | 40 |
| 1  | bar | 50 |
| 2  | foo | 40 |
| 2  | bar | 50 |
| 2  | cod | 0  |
| 3  | foo | 40 |
| 3  | bar | 50 |

до

| id | A   | B  |
|----|-----|----|
| 1  | foo | 40 |
| 1  | bar | 50 |
| 2  | foo | 40 |
| 2  | bar | 50 |
| 2  | cod | 0  |

Здесь я сгруппировал по id, а затем удалил 3, потому что, если мы рассмотрим только столбцы A и B, они идентичны, тогда как в группе 2 есть несколько дублированных строк, но это не точная копия.

I 'мы пробовали зацикливаться на группах, но это очень медленно, хотя существует только около 12.000 групп.Одним из возможных осложнений является то, что группы имеют переменные размеры.

Вот решение, над которым я работал, но оно заняло много времени без видимых дублированных попаданий (которые, как я знаю, существует в этой базе данных)

grps = datafinal.groupby('Form_id') 
unique_grps={}

first=True
for lab1, grp1 in grps:
    if first:
        unique_grps[lab1] = grp1
        first=False
        continue
    for lab2, grp2 in unique_grps.copy().items():
        if grp2[['A','B']].equals(grp1[['A','B']]):
            print("hit")
            continue
        unique_grps[lab1] = grp1

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Вы можете использовать рецепт unique_everseen из документов itertools (также находится в библиотеке more_itertools) вместе с pd.concat и groupby:

from operator import itemgetter
from more_itertools import unique_everseen

def unique_key(x):
    return tuple(map(tuple, x[['A', 'B']].values.tolist()))

def jpp(df):
    groups = map(itemgetter(1), df.groupby('id'))
    return pd.concat(unique_everseen(groups, key=unique_key))

print(jpp(df))

   id    A   B
0   1  foo  40
1   1  bar  50
2   2  foo  40
3   2  bar  50
4   2  cod   0
0 голосов
/ 03 декабря 2018

Использование agg tuple и duplicated

s=df.groupby('id').agg(tuple).sum(1).duplicated()
df.loc[df.id.isin(s[~s].index)]
Out[779]: 
   id    A   B
0   1  foo  40
1   1  bar  50
2   2  foo  40
3   2  bar  50
4   2  cod   0

Дополнительная информация: прямо сейчас все в группе в одном tuple

df.groupby('id').agg(tuple).sum(1)
Out[780]: 
id
1            (foo, bar, 40, 50)
2    (foo, bar, cod, 40, 50, 0)
3            (foo, bar, 40, 50)
dtype: object

Обновление

from natsort import natsorted
s=df.groupby('id').agg(tuple).sum(1).map(natsorted).map(tuple).duplicated()
...