Как сравнить pandas dataframe с его обновленной версией? - PullRequest
2 голосов
/ 26 сентября 2019

У меня есть фрейм данных и обновленная версия того же фрейма данных с измененным цветом в строке 1, строкой 2 и одной строкой.

Я хотел бы добавить строки с новым идентификатором встарый кадр данных, затем сравните оба кадра данных и запишите результат сравнения (например, «Новая запись», «Обновленный цвет», «Запись удалена» или «Без изменений») в столбец «Сравнить».

   Name  Colour      ID Compare
0  Lisa     Red   Apple        
1  Anna    Blue  Banana        
2  Anna  Yellow  Orange        
3   Max   Green    Pear   


    Name  Colour      ID
0   Lisa  Purple   Apple
1   Anna  Yellow  Orange
2  Peter    Pink   Grape

Я пробовал несколько подходов с .iloc и .where, однако я слишком неопытен в выборе / манипулировании, так что это не сработало.Вот что я пытаюсь достичь:

   Name  Colour      ID         Compare
0  Lisa     Red   Apple  Colour changed
1  Anna    Blue  Banana   Entry deleted
2  Anna  Yellow  Orange      No changes
3   Max   Green    Pear       New entry

Я благодарен за любую помощь.

Это для создания фреймов данных:

import pandas as pd

data = {'Name': ['Lisa', 'Anna', 'Anna', 'Max'],
        'Colour': ['Red', 'Blue', 'Yellow', 'Green'],
        'ID': ['Apple', 'Banana', 'Orange', 'Pear'],
        'Compare': ['','','','']}

df = pd.DataFrame(data, columns = ['Name', 'Colour', 'ID', 'Compare'])
updatedDf = df.copy()
updatedDf = updatedDf.iloc[:, :-1]
updatedDf.set_value(0, 'Colour', 'Purple')
updatedDf = updatedDf.drop(1)
newrow = ['Peter', 'Pink', 'Grape']
updatedDf.loc[len(updatedDf)] = newrow
updatedDf = updatedDf.reset_index(drop=True)

1 Ответ

1 голос
/ 26 сентября 2019

Вы можете создать DataFrame со старой и новой версией бок о бок с внешним объединением

>> df2 = pd.merge(df, updatedDf, on ='ID', how='outer', suffixes=['', '_update'])
   Name  Colour      ID Compare Name_update Colour_update
0  Lisa     Red   Apple                Lisa        Purple
1  Anna    Blue  Banana                 NaN           NaN
2  Anna  Yellow  Orange                Anna        Yellow
3   Max   Green    Pear                 NaN           NaN
4   NaN     NaN   Grape     NaN       Peter          Pink

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

  1. Если Name и Colour равны NaN, запись является новой
  2. Если Name_updated и Colour_updated равны NaN, запись была удалена
  3. Если Name и Colour оба равны Name_updated и Colour_updated, запись не изменилась
  4. Если Name и Name_updated равны, но Color и Colour_updated не совпадают, цвет был изменен
  5. И наоборот, если имя изменилось
  6. Если Name и Colour не равны Name_updated и Colour_updated, вы еще не определили ожидаемое поведение

Помните, что это не учитывает крайние случаи, например, когда было удалено только одно поле или идентификаторы не являются уникальными

Вы можете инкапсулировать все эти условные выражения в функцию и использовать метод apply или просто сделать это с помощью copy-pasteвот так

df2.loc[df2[['Name', 'Colour']].isnull().any(axis=1), 'Compare'] = 'New entry'
df2.loc[df2[['Name_updated', 'Colour_updated']].isnull().any(axis=1), 'Compare'] = 'Entry deleted'
df2.loc[(~df2[['Name', 'Colour', 'Name_updated', 'Colour_updated']].isnull().any(axis=1)) & (df2['Name'] == df2['Name_updated']) & (df2['Colour'] == df2['Colour_updated']), 'Compare'] = 'No changes'
df2.loc[(~df2[['Name', 'Colour', 'Name_updated', 'Colour_updated']].isnull().any(axis=1)) & (df2['Name'] == df2['Name_updated']) & (df2['Colour'] != df2['Colour_updated']), 'Compare'] = 'Colour changed'
df2.loc[(~df2[['Name', 'Colour', 'Name_updated', 'Colour_updated']].isnull().any(axis=1)) & (df2['Name'] != df2['Name_updated']) & (df2['Colour'] == df2['Colour_updated']), 'Compare'] = 'Name changed'
df2.loc[(~df2[['Name', 'Colour', 'Name_updated', 'Colour_updated']].isnull().any(axis=1)) & (df2['Name'] != df2['Name_updated']) & (df2['Colour'] != df2['Colour_updated']), 'Compare'] = 'Name and colour changed'

Хотя это немного сложно, проверить, что ни одна из записей не является NaN,cessary в последних 4 заявлениях.Сравнение с NaN всегда верно, так что это немного безопаснее.

Принимайте новые значения везде, где вы можете

df2['Name'].update(df2['Name_updated'])                                                                                                                                                                   
df2['Colour'].update(df2['Colour_updated'])

Используемый здесь метод Series.update пропускает строкигде значения, где удаляются автоматически.

В конце вы можете выбросить временные столбцы.

df2.drop(['Name_updated', 'Colour_updated'], axis=1, inplace=True)                                                                                                                                                      

    Name  Colour      ID         Compare
0   Lisa  Purple   Apple  Colour changed
1   Anna    Blue  Banana   Entry deleted
2   Anna  Yellow  Orange      No changes
3    Max   Green    Pear   Entry deleted
4  Peter    Pink   Grape       New entry

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...