Панды - являются ли определенные строки dataframeA подмножеством определенных строк dataframeB?

1

У меня есть два фрейма данных dfA и dfB:

dfA = 
   entityId entityName property value
0         1        bob    propA     a
1         1        bob    propB     b
2         1        bob    propC     c
3         2       dave    propA    aa
4         2       dave    propC     c
5         3        bob    propA     a
6         3        bob    propB    bb
7         3        bob    propD     d
8         4       alex    propE    ee
9         4       alex    propF   fff

dfB = 
   entityId entityValid property value propValid  propId
0       123         yes    propA     a       yes  1
1       123         yes    propB     b       yes  2
2       123         yes    propC     c       yes  3
3       124          no    propA    aa        no  4
4       124          no    propC     c       yes  3
5       125    not sure    propA     a       yes  1
6       125    not sure    propB    bb       yes  5
7       125    not sure    propD     d       yes  6
8       126          no    propE    ee       yes  7
9       126          no    propF    FF       yes  8

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

Будет ли наиболее целесообразно разблокировать кадры данных и сначала выразить каждую сущность в одной строке? Конечный результат, который я искал, будет таким, как будто это, однако, любой вклад о том, как подойти к проблеме, оценен.

resultDf =
      entityId entityName  dfBEntityIdMatch  valid    invalidProps
0            1        bob  123               yes      ()
1            2       dave  124               no       (4)
2            3        bob  125               not sure ()
3            4       alex  '---'             '---'    '---'

Заранее спасибо.

Код для создания данных:

import pandas as pd
pd.set_option('display.max_columns',20)

dfA = pd.DataFrame([[1, 'bob', 'propA', 'a'],
                    [1, 'bob', 'propB', 'b' ],
                    [1, 'bob', 'propC', 'c' ],
                    [2, 'dave', 'propA', 'aa' ],
                    [2, 'dave', 'propC', 'c' ],
                    [3, 'bob', 'propA', 'a' ],
                    [3, 'bob', 'propB', 'bb' ],
                    [3, 'bob', 'propD', 'd' ],
                    [4, 'alex', 'propE', 'ee' ],
                    [4, 'alex', 'propF', 'fff' ]],
                   columns=['entityId', 'entityName', 'property', 'value'])

dfB = pd.DataFrame([[123, 'yes', 'propA', 'a', 'yes', 1],
                    [123, 'yes', 'propB', 'b', 'yes', 2],
                    [123, 'yes', 'propC', 'c', 'yes', 3],
                    [124, 'no', 'propA', 'aa', 'no', 4],
                    [124, 'no', 'propC', 'c', 'yes', 3],
                    [125, 'not sure', 'propA', 'a', 'yes', 1 ],
                    [125, 'not sure', 'propB', 'bb', 'yes', 5 ],
                    [125, 'not sure', 'propD', 'd', 'yes', 6 ],
                    [126, 'no', 'propE', 'ee', 'yes', 7],
                    [126, 'no', 'propF', 'FF', 'yes', 8 ]],
                   columns=['entityId', 'entityValid', 'property', 'value', 'propValid', 'propId'])
Теги:
pandas

1 ответ

1
Лучший ответ

вот один из способов получить что-то похожее на ваш ожидаемый результат, по крайней мере, на данные, которые вы предоставляете. Сначала создайте столбец "invalidProps" в dfB

dfB.loc[dfB['propValid'] == 'no','invalidProps'] = dfB.loc[dfB['propValid'] == 'no','propId']
dfB['invalidProps'] = dfB['invalidProps'].fillna('')

Теперь вы можете использовать groupby как groupby независимо, так и agg с различными методами. Вам нужно sort_values по свойствам и "значению", если ваши реальные данные не находятся в одном и том же порядке между dataframe

dfA_g = (dfA.sort_values(['property', 'value'])
              .groupby(['entityId','entityName'],as_index=False).agg(tuple))
dfB_g = (dfB.sort_values(['property', 'value'])
              .groupby(['entityId','entityValid'],as_index=False)
               .agg({'property':lambda x: tuple(x), 
                     'value':lambda x: tuple(x), 
                     'invalidProps':lambda x: tuple(filter(None,x))}))

Теперь вы можете merge с "свойством" и "значением" и использовать fillna для замены значений nan, drop ненужные столбцы и rename одну из них:

resultDf  = (dfA_g.merge(dfB_g, how='left', on=['property', 'value'],suffixes=('','_'))
                  .fillna('---').drop(['property', 'value'],1)
                  .rename(columns={'entityId_':'dfBEntityIdMatch', 'entityValid':'valid'}))

и вы получите что-то вроде:

   entityId entityName dfBEntityIdMatch     valid invalidProps
0         1        bob              123       yes           ()
1         2       dave              124        no       (4.0,)
2         3        bob              125  not sure           ()
3         4       alex              ---       ---          ---
  • 1
    Удивительно! Большое спасибо Ben.T

Ещё вопросы

Сообщество Overcoder
Наверх
Меню