簡體   English   中英

有趣的 Pandas dataframe 問題:如何在兩列上刪除重復項(反向)- 對於具有共同屬性的每一行?

[英]Interesting Pandas dataframe problem: how to drop duplicates (inverse) over two columns - for each row with a common attribute?

過濾掉反向重復項后,我必須計算實際有多少重復項。 這是我的(工作示例)代碼,但它太慢了,對於 90 000 多行......使用 iterrows:

import pandas as pd

data = {'id_x':[1,2,3,4,5,6],      
'ADDICTOID_x':['BFO:0000023', 'MF:0000016', 'BFO:0000023', 'MF:0000016', 'MF:0000016', 'ADDICTO:0000872'],     
'PMID':[34116904, 34116904, 34112174, 34112174, 34112174, 22429780],                  
'LABEL_x':['role', 'human being', 'role', 'human being', 'human being', 'FDA'],   
'id_y':[11,12,13,14,15,16],    
'ADDICTOID_y':['MF:0000016', 'BFO:0000023', 'MF:0000016', 'BFO:0000023', 'BFO:0000023', 'ADDICTO:0000904'],                
'LABEL_y':['human being', 'role', 'human being', 'role', 'role', '']}
dcp = pd.DataFrame(data)

dcp = dcp.drop(dcp[dcp.LABEL_x == dcp.LABEL_y].index)

for index, row in dcp.iterrows():  # THIS IS SLOW
        if ((dcp['ADDICTOID_x'] == row['ADDICTOID_y'])
            & (dcp['ADDICTOID_y'] == row['ADDICTOID_x'])
            & (dcp['PMID'] == row['PMID'])).any():  # Does the inverse of this row exist in the table?
            dcp.drop(index, inplace=True)

print("dcp after drop: ")
print(dcp)

我不能只使用dcp.duplicated(subset=['ADDICTOID_x', 'ADDICTOID_y'], keep='first')因為這樣會刪除所有重復項(有很多),我只想一個一個地做,並且“PMID”也需要匹配。 類似地, (dcp.ADDICTOID_x + dcp.ADDICTOID_y).isin(dcp.ADDICTOID_y + dcp.ADDICTOID_x) & (dcp.PMID == dcp.PMID)發現到處都是重復的行。 Iterrows 並逐一測試是我發現的唯一有效方法,但它太慢了。 有人知道解決這個問題的方法嗎?

過濾反向重復項后,我這樣計數: data_chord_plot = dcp.groupby(['LABEL_x', 'LABEL_y'], as_index=False)[['PMID']].count() data_chord_plot.columns = ['source','target','value']

編輯:在這個簡單的例子中,第 1 行和第 3 行被刪除,因為它們是第 2 行和第 4 行的反向副本。

編輯:我需要消除在兩列上具有反向重復項的行的“鏡像”圖像,但每行只有一個具有重復項。 有些行沒有鏡像。

從(慢)示例中更正 OUTPUT:

id_x ADDICTOID_x PMID LABEL_x id_y ADDICTOID_y LABEL_y

1 2 MF:0000016 34116904 人類 12 BFO:0000023 角色

3 4 MF:0000016 34112174 人類 14 BFO:0000023 角色

4 5 MF:0000016 34112174 人類 15 BFO:0000023 角色

5 6 癮君子:0000872 22429780 FDA 16 癮君子:0000904

也許有更短的方法,但我可以考慮將df與其逆向自我合並,然后只留下沒有先前匹配的行。 所以代替你的循環做:

dcp = dcp.merge(dcp[['id_x', 'PMID', 'ADDICTOID_x', 'ADDICTOID_y']].rename({'id_x': 'inv_id', 'ADDICTOID_x': 'inv_y', 'ADDICTOID_y': 'inv_x'}, axis=1), how='left')
dcp['was'] = (dcp['ADDICTOID_x'] == dcp['inv_x']) & (dcp['ADDICTOID_y'] == dcp['inv_y']) & (dcp['id_x'] > dcp['inv_id'])
dcp = dcp.sort_values(['id_x', 'was']).drop_duplicates('id_x', keep='last')
dcp = dcp.loc[~dcp['was'], 'id_x': 'LABEL_y']

創建一個drop_duplicates ADDICTOID_xy正確的子集一起使用:

dcp['ADDICTOID'] = dcp[['ADDICTOID_x', 'ADDICTOID_y']].apply(sorted, axis=1) \
                                                      .apply(tuple)

out = dcp.drop_duplicates(subset=['ADDICTOID', 'PMID'], keep='first')
>>> out
   id_x      ADDICTOID_x      PMID LABEL_x  id_y      ADDICTOID_y      LABEL_y                           ADDICTOID
0     1      BFO:0000023  34116904    role    11       MF:0000016  human being           (BFO:0000023, MF:0000016)
2     3      BFO:0000023  34112174    role    13       MF:0000016  human being           (BFO:0000023, MF:0000016)
5     6  ADDICTO:0000872  22429780     FDA    16  ADDICTO:0000904               (ADDICTO:0000872, ADDICTO:0000904)

暫無
暫無

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

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