簡體   English   中英

Python-比較數據框中的兩列

[英]Python - compare two columns in dataframe

我有兩個文件,兩者之間有微小差異。 我想輸出不同的值,以便可以看到更改的內容。 有很多要比較的列。

這是示例數據(示例中唯一的區別是第一行的狀態):

數據1

ID      PROGRAM_CODE    Status
123     888             Active
123     777             Active
345     777             Inactive
345     999             Active
678     666             Inactive
901     777             Inactive
901     888             Active

數據2

ID      PROGRAM_CODE    Status
123     888             BLAH
123     777             Active
345     777             Inactive
345     999             Active
678     666             Inactive
901     777             Inactive
901     888             Active

所需輸出:

ID      Status_1    Status_2
123     Active      Inactive

我當前的方法是創建列列表,合並兩個數據框,然后在for循環中使用列列表進行比較。 我相信我的代碼會比較系列並輸出整個系列(如果有任何區別的話)。 我只想查看具有不同值的一行。 此外,如果一個字段具有值,而另一字段中為空白,則此方法不起作用。

碼:

import pandas as pd

df1 = pd.read_excel(r"P:\data_files\data1.xlsx")
df2 = pd.read_excel(r"P:\data_files\data2.xlsx")


# create list of columns
l1 = list(df1)


# dropping the join values from the list because I don't want to compare those
l1 = [e for e in l1 if e not in ('ID','PROGRAM_CODE')]

# merge dataframes
df3 = df1.merge(df2, how='outer', on=['ID','PROGRAM_CODE'], suffixes=['_1', '_2'])

for x in l1:
    if df3[x+'_1'].any() != df3[x+'_2'].any():
        print(df3[['ID', x+'_1',x+'_2']])

上面的代碼的輸出:即使只有第一行的數據幀之間的值不同,也會顯示“狀態”列的所有值。

ID      Status_1    Status_2
123     Active      Blah
123     Active      Active
345     Inactive    Inactive
345     Active      Active
678     Inactive    Inactive
901     Inactive    Inactive
901     Active      Active

編輯12/12/17下面來自Wen的示例似乎適用於一列,但是我需要比較ID和Program_Code相同的兩個文件的每一行和每一列。

我嘗試了以下循環:

for x in l1:
    print(df3.groupby('STUDENT_CID').x.apply(list).apply(pd.Series).add_prefix(x+'_'))

但我收到以下錯誤:

AttributeError: 'DataFrameGroupBy' object has no attribute 'x'

我需要一種遍歷每一列的方式(兩個文件都包含相同的列)。

附加示例:

數據文件1

ID      PROGRAM_CODE    I_CODE  INSTITUTION TERM    TYPE    STATUS      Hire_Date
123     888             111     ZBD         Fall    FINAL   Active      1/1/2017 0:00
123     777             111     ZBD         Fall    FINAL   Active      1/1/2017 0:00
345     777             125     GUB         Fall    FINAL   Inactive    2/3/2017 0:00
345     999             125     GUB         Fall    FINAL   Inactive    2/3/2017 0:00
678     999             111     ZBD         Fall    FINAL   Active      1/1/2017 0:00
678     888             111     ZBD         Fall    FINAL   Active      1/1/2017 0:00
901     888             654     YUI         Fall    FINAL   Inactive    5/1/2017 0:00
901     777             654     YUI         Fall    FINAL   Inactive    5/1/2017 0:00

數據文件2

ID      PROGRAM_CODE    I_CODE  INSTITUTION TERM    TYPE    STATUS      Hire_Date
123     888             111     ZBD         Fall    FINAL   Inactive    1/1/2017 0:00
123     777             111     ZBD         Fall    FINAL   Active      1/1/2017 0:00
345     777             111     ZBD         Fall    FINAL   Inactive    2/3/2017 0:00
345     999             111     ZBD         Fall    FINAL   Inactive    2/3/2017 0:00
678     999             111     ZBD         Fall    FINAL   Active      1/1/2017 0:00
678     888             111     ZBD         Fall    FINAL   Active      1/1/2017 0:00
901     888             654     YUI         Fall    FINAL   Inactive    5/1/2017 0:00
901     777             654     YUI         Fall    FINAL   Inactive    5/1/2017 0:00

期望的輸出

ID  STATUS_1        STATUS_2
123 Active          Inactive

ID  INSTITUTION_1   INSTITUTION_2
345 125             111

我們使用pd.concat + drop_duplicates

df1=pd.concat([df1,df2]).drop_duplicates(keep=False)
df1
Out[1085]:
    ID  PROGRAM_CODE  Status
0  123           888  Active
0  123           888    BLAH

然后我們groupby創建您需要的表

df1.groupby('ID').Status.apply(list).apply(pd.Series).add_prefix('Status_')
Out[1094]: 
    Status_0 Status_1
ID                   
123   Active     BLAH

更新

df=pd.concat([df1,df2]).drop_duplicates(keep=False)
dd=df.groupby('ID').agg(lambda x:sorted(set(x), key=list(x).index)).stack()

dd[dd.apply(len)>1]
Out[1194]: 
ID               
123  STATUS          [Active, Inactive]
345  PROGRAM_CODE            [777, 999]
     I_CODE                  [125, 111]
     INSTITUTION             [GUB, ZBD]

我確定有更好的方法來執行此操作,但是您是否嘗試過合並數據框(如您現有的那樣),創建一個比較Status_1和Status_2的新列,然后刪除匹配項為True的任何行? 如果您之后刪除了“它們是否匹配”列,我相信您會獲得理想的輸出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM