оператор if и между pandas фреймами данных - PullRequest
0 голосов
/ 12 марта 2020

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

  • Условия:

Если строка столбца df1 «Имя» совпадает более чем на 80% с любой строкой столбца «Имя» в df2

(AND)

(df1 ['Class) '] == df2 [' Class '] (OR) df1 [' Amt $ '] == df2 [' Amt $ '])

(AND)

Если строка из категории Столбец 'в df1 более 80% соответствует любому элементу строки в столбце' Категория 'в df2

  • Результат:

если все условия соблюдены, сохраните только новые данные в df2 и удалите остальные строки.

df1

Name    Class   Amt $   Category
Apple      1    5       Fruit
Banana     2    8       Fruit
Cat        3    4       Animal

df2

Index   Name              Class Amt $   Category
    1   Apple is Red       1    5       Fruit
    2   Banana             2    8       fruits
    3   Cat is cute        3    4       animals
    4   Green Apple        1    5       fruis
    5   Banana is Yellow   2    8       fruet
    6   Cat                3    4       anemal
    7   Apple              1    5       anemal
    8   Ripe Banana        2    8       frut
    9   Royal Gala Apple   1    5       Fruit
    10  Cats               3    4       animol
    11  Green Banana       2    8       Fruit
    12  Green Apple        1    5       fruits
    13  White Cat          3    4       Animal
    14  Banana is sweet    2    8       appel
    15  Apple is Red       1    5       fruits
    16  Ginger Cat         3    4       fruits
    17  Cat house          3    4       animals
    18  Royal Gala Apple   1    5       fret
    19  Banana is Yellow   2    8       fruit market
    20  Cat is cute        3    4       anemal

  • Код, который я пробовал:

for i in df1['Name']:
    for u in df2['Name']:
        for k in df1['Class']:
            for l in df2['Class']:
                for m in df1['Amt $']:
                    for n in df2['Amt $']:
                        for o in df1['Category']:
                            for p in df2['Category']:
                                if SequenceMatcher(None, i, u).ratio() > .8 and k == l and m == n and SequenceMatcher(None, o, p).ratio() > 0.8:
                                    print(i, u)

Желаемый выходной кадр данных должен выглядеть примерно так:

Name              Class Amt $   Category
Apple is Red        1   5       Fruit
Banana              2   8       fruits
Cat is cute         3   4       animals
Green Apple         1   5       fruis
Banana is Yellow    2   8       fruet
Cat                 3   4       anemal
Ripe Banana         2   8       frut
Royal Gala Apple    1   5       Fruit
Cats                3   4       animol
Green Banana        2   8       Fruit
Green Apple         1   5       fruits
White Cat           3   4       Animal
Apple is Red        1   5       fruits
Cat house           3   4       animals
Banana is Yellow    2   8       fruit market
Cat is cute         3   4       anemal

Пожалуйста, помогите мне с лучшим решением! :)

1 Ответ

1 голос
/ 12 марта 2020

Сначала вы должны перебрать оба dfs и сопоставить, используя условия и установить переменную в df2.

df2['match'] = False
for idx2, row2 in df2.iterrows():
    match = False
    for idx1, row1 in df1.iterrows():
        if (SequenceMatcher(None, row1['Name'], row2['Name']).ratio())>=0.8 and \
                (SequenceMatcher(None, row1['Category'], row2['Category']).ratio())>=0.8 and \
                (row1['Class'] == row2['Class'] or row1['Amt $'] == row2['Amt $']):
            match = True
            break
    df2.at[idx2, 'match'] = match

Как только у вас есть совпадения, вы удаляете дубликаты из совпадений df2['match']==True.

df2[df2['match']==True].drop_duplicates(keep='first')

Далее вы можете объединить приведенный выше результат с несоответствиями df2['match']==False

df2[df2['match']==False].append(df2[df2['match']==True].drop_duplicates(keep='first'))

Здесь я предполагаю, что вы хотите удалить прямые дубликаты. Вы хотите удалить дубликаты на основе условий или прямых дубликатов?

На основании набора тестовых данных, которые у вас есть, «Apple» и «Apple is red» соответствуют 80%. Но SequenceMatcher(None, 'Apple', 'Apple is Red').ratio() дает только 0,5882352941176471. Точно так же SequenceMatcher(None, 'Fruit', 'fruits').ratio() составляет всего 0,7272727272727273. Вы ожидаете чего-то еще здесь? или ожидаемый результат не так?

В любом случае, я надеюсь, что это даст вам представление о подходе.

РЕДАКТИРОВАТЬ 1 Если вы хотите получить соответствующий df1['Name'].

Я только сбросил df2['match'] как строку вместо логического значения и назначил df1['Name'] на df2['match'] вместо назначения True. Затем в последнем df я объединяю строки df2, которые имеют df2['match']==False, и строки, не являющиеся дубликатами df2['match']==True. Надеюсь это поможет.

df2['match'] = ''
for idx2, row2 in df2.iterrows():
    match = ''
    for idx1, row1 in df1.iterrows():
        if (SequenceMatcher(None, row1['Name'], row2['Name']).ratio())>=0.5 and \
                (SequenceMatcher(None, row1['Category'], row2['Category']).ratio())>=0.5 and \
                (row1['Class'] == row2['Class'] or row1['Amt $'] == row2['Amt $']):
            match = row1['Name']
            break
    df2.at[idx2, 'match'] = match


print(df2[df2['match']==''].append(df2[df2['match']!=''].drop_duplicates(keep='first')))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...