我有一个数据框和同一数据框的更新版本,其中第1行的颜色已更改,第2行已删除,并附加了一行。
我想将具有新ID的行附加到旧数据框,然后比较两个数据框并写入比较结果(例如“新条目”,“颜色更新”,“条目删除”或“无更改” )添加到“比较”列中。
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)
答案 0 :(得分:1)
您可以使用外部联接并排创建新版本和旧版本的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
现在,您需要定义如何识别每种情况:
Name
和Colour
是NaN,则该条目是新的Name_updated
和Colour_updated
为NaN,则该条目已删除Name
和Colour
都等于Name_updated
和Colour_updated
,则该条目未更改Name
和Name_updated
相等,但Color
和Colour_updated
不相等,则表示颜色已更改Name
和Colour
都不等于Name_updated
和Colour_updated
,则您尚未定义预期的行为请注意,这不会处理边缘情况,例如当只有一个字段被删除或ID不唯一时
您可以将所有条件包封装到一个函数中,然后使用apply或仅通过复制粘贴来做到这一点
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'
尽管有些复杂,但是在最后4条语句中必须检查所有条目都不是NaN
。与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