比较具有不同行数的数据帧 - pandas

时间:2017-11-02 13:41:21

标签: python pandas dataframe difference

我正在开发一个允许我输出两个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是实现我的目标的正确方法。也许前面有完全不同的方法。外合并?我已经查看了多个解决方案,但没有一个解决方案包括添加密钥和排序。

任何提示赞赏。

1 个答案:

答案 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