我正在开发一个允许我输出两个csv文件差异的程序。下面是一些虚拟数据的示例。
输入:
timestamp
期望的输出:
import pandas as pd
df1 = pd.DataFrame([['vegetable', 100, 'orange', 12, 'carrot'],
['fruit', 150, 'green', 10, 'apple'],
['vegetable', 175, 'white', 3, 'colifower'],
['fruit', 210, 'orange', 1, 'tangerine'],
['vegetable', 75, 'black', 120, 'old_carrot']],
columns=['type', 'weight', 'colour', 'days_in_basket', 'name'])
df2 = pd.DataFrame([['vegetable', 100, 'orange', 12, 'carrot'],
['fruit', 150, 'green', 10, 'apple'],
['fruit', 200, 'red', 1, 'apple'],
['vegetable', 500, 'green', 2, 'cabbage'],
['vegetable', 170, 'white', 4, 'colifower'],
['fruit', 210, 'orange', 1, 'tangerine'],
['vegetable', 70, 'black', 122, 'very_old_carrot']],
columns=['type', 'weight', 'colour', 'days_in_basket', 'name'])
因为我们没有密钥(ID)问题是匹配来自两个数据帧的已更改行并且区分完全新的行。
为了克服这个问题,我提出了以下概念:
定义键选择多个列(如果键不唯一则引发异常),然后使用定义的键对行进行排序,删除过多的行(第二个数据帧中的行数始终更高)并比较数据帧。
定义密钥是在用户端。
我不知道如何使用MultiIndex作为键,或者MultiIndex是实现我的目标的正确方法。也许前面有完全不同的方法。外合并?我已经查看了多个解决方案,但没有一个解决方案包括添加密钥和排序。
任何提示赞赏。
答案 0 :(得分:0)
首先左外连接两个数据帧。
>>> combined_df=df2.merge(df1,on=['type','colour','name'],how='left')
>>> combined_df
type weight_x colour days_in_basket_x name weight_y \
0 vegetable 100 orange 12 carrot 100
1 fruit 150 green 10 apple 150
2 fruit 200 red 1 apple NaN
3 vegetable 500 green 2 cabbage NaN
4 vegetable 170 white 4 colifower 175
5 fruit 210 orange 1 tangerine 210
6 vegetable 70 black 122 old_carrot 75
days_in_basket_y
0 12
1 10
2 NaN
3 NaN
4 3
5 1
6 120
当两个数据帧连接在一起时,df2中的额外行将在df1的列中具有Nan。 因此,我们需要使用Nan过滤这些行以获取extra_df。
>>> extra_df=df2[combined_df['weight_y'].isnull()].reset_index(drop='True')
>>> extra_df
type weight colour days_in_basket name
0 fruit 200 red 1 apple
1 vegetable 500 green 2 cabbage
要获取change_df,首先需要删除额外的行。此外,需要删除没有任何更改的行。
>>> no_extra_df=combined_df[~combined_df['weight_y'].isnull()]
>>> changed_df_temp=no_extra_df[(no_extra_df['weight_x']!=no_extra_df['weight_y']) & (no_extra_df['days_in_basket_x']!=no_extra_df['days_in_basket_y'])].reset_index(drop=True)
>>> changed_df_temp
type weight_x colour days_in_basket_x name weight_y \
0 vegetable 170 white 4 colifower 175
1 vegetable 70 black 122 old_carrot 75
days_in_basket_y
0 3
1 120
最后,列weight_x,weight_y和days_in_basket_x,days_in_basket_y应与 - >
连接>>> change_df_temp['weight']=change_df_temp.apply(lambda x : str(x['weight_y'])+'->'+str(x['weight_x']),axis=1)
>>> change_df_temp['days_in_basket']=change_df_temp.apply(lambda x : str(x['days_in_basket_y'])+'->'+str(x['days_in_basket_x']),axis=1)
>>>
>>> change_df=change_df_temp[['type', 'weight', 'colour', 'days_in_basket', 'name']]
>>> change_df
type weight colour days_in_basket name
0 vegetable 175->170 white 3->4 colifower
1 vegetable 75->70 black 120->122 old_carrot