Поиск дублирующихся значений групп Acorss в Pandas GroupBy - PullRequest
4 голосов
/ 19 января 2020
df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar',
                         'foo', 'bar', 'foo', 'foo'],
                   'B': ['one', 'one', 'two', 'three',
                         'two', 'two', 'one', 'three'],
                   'C': [3,4,5,8,10,12,14,12]})
df.groupby(['A','B']).sum()

enter image description here

Как определить, повторяются ли значения в столбце C и в других группах? (Здесь 12 повторяется в обеих группах)

Ответы [ 2 ]

2 голосов
/ 19 января 2020

Чтобы показать более поучительный пример, я добавил одну строку в ваш исходный DataFrame, чтобы он содержал:

     A      B   C
0  foo    one   3
1  bar    one   4
2  foo    two   5
3  bar  three   8
4  foo    two  10
5  bar    two  12
6  foo    one  14
7  foo  three  12
8  xxx    yyy   8

Я сохранил результат группировки в другом DataFrame:

df2 = df.groupby(['A','B']).sum()

так что он содержит:

            C
A   B        
bar one     4
    three   8
    two    12
foo one    17
    three  12
    two    15
xxx yyy     8

Итак, как вы можете видеть, есть два повторяющихся значения в C: 12 и 8 . Обратите внимание, что теперь индекс в df2 является уникальным .

Затем, чтобы показать повторяющиеся значения и их группы, выполните:

df2[df2.duplicated(keep=False)].sort_values('C')

получение:

            C
A   B        
bar three   8
xxx yyy     8
bar two    12
foo three  12

Приведенный выше результат показывает все повторяющиеся значения и группы ( A и B ), в которых они находятся.

2 голосов
/ 19 января 2020

Идея заключается в преобразовании MultIndex в 3 столбца DataFrame, затем DataFrame.pivot с удалением недублированных строк на DataFrame.dropna, а общие значения в индексе:

df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar',
                         'foo', 'bar', 'foo', 'foo'],
                   'B': ['one', 'one', 'two', 'three',
                         'two', 'two', 'one', 'three'],
                   'C': [3,4,5,8,10,12,14,12]})
df = df.groupby(['A','B']).sum()

common = df.reset_index().pivot('C','A','B').dropna().index
print (common)
Int64Index([12], dtype='int64', name='C')

Тогда, если хотите отфильтровать исходные данные, используйте boolean indexing:

df = df[df['C'].isin(common)]
print (df)
            C
A   B        
bar two    12
foo three  12

Если хотите, чтобы общие строки дублировались хотя бы в 2 группах, решением является:

print (df)  
     A      B   C
0  foo    one   3
1  bar    one   4
2  foo    two   3
3  bar  three   8
4  foo    two  14
5  bar    two  12
6  foo    one  14
7  foo  three  12
8  xxx    yyy   8

df = df.groupby(['A','B']).sum()
print (df)
            C
A   B        
bar one     4
    three   8 <- dupe per bar, three
    two    12 <- dupe per bar, two
foo one    17 <-17 is duplicated per group foo, one, so omited
    three  12 <- dupe per foo, three
    two    17 <-17 is duplicated per group foo, one, so omited
xxx yyy     8 <- dupe per xxx, yyy

common1 = (df.reset_index()
             .pivot_table(index='C',columns='A', values='B', aggfunc='size')
             .notna()
             .sum(axis=1)
            )
common1 = common1.index[common1.gt(1)]
print (common1)
Int64Index([8, 12], dtype='int64', name='C')

df1 = df[df['C'].isin(common1)]
print (df1)
            C
A   B        
bar three   8
    two    12
foo three  12
xxx yyy     8
...