python - 如何将 pandas 数据框与其更新版本进行比较?
问题描述
我有一个数据框和同一数据框的更新版本,第 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)
解决方案
您可以使用外部连接并排创建具有旧版本和新版本的 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'
虽然有点复杂,但NaN
在最后 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
推荐阅读
- android - 手机已锁定 - Vysor 将键盘隐藏在我的手机上
- c# - 通过按下按钮扩展表格
- c# - 关闭弹窗后如何执行一组命令
- azure - Azure AD B2C 配置多重登录策略
- javascript - 无法在 JavaScript 承诺中为变量设置适当的范围
- jquery-ui - 使用 jquery.layout,调整北面板高度时如何调整容器高度
- css - css大边距但边框重叠
- c++ - 无法解码 base64+deflate 数据
- angular - 没有路由器的角度延迟加载模块
- angular - 在 Typescript 和 Angular 7 中导入运行时可配置的 JSON