2013-05-02 314 views
3

我在刪除重複項時遇到問題。我的程序基於一個生成元組(x,y)的循環,然後這些元組用作圖形中的節點。節點的最後陣列/矩陣爲:刪除Python中的重複項Pandas DataFrame不刪除重複項

[[ 1.   1.  ] 
[ 1.12273268 1.15322175] 
[..........etc..........] 
[ 0.94120695 0.77802849] 
**[ 0.84301344 0.91660517]** 
[ 0.93096269 1.21383287] 
**[ 0.84301344 0.91660517]** 
[ 0.75506418 1.0798641 ]] 

數組的長度爲22。現在,我需要刪除重複的條目(見**)。所以我用:

def urows(array): 
    df = pandas.DataFrame(array) 
    df.drop_duplicates(take_last=True) 
    return df.drop_duplicates(take_last=True).values 

好極了,但我仍然得到:

  0   1 
0 1.000000 1.000000 
....... etc........... 
17 1.039400 1.030320 
18 0.941207 0.778028 
**19 0.843013 0.916605** 
20 0.930963 1.213833 
**21 0.843013 0.916605** 

因此下降重複不消除任何。我測試過,看看實際上和我得到的節點是否相同:

print urows(total_nodes)[19,:] 
---> [ 0.84301344 0.91660517] 
print urows(total_nodes)[21,:] 
---> [ 0.84301344 0.91660517] 
print urows(total_nodes)[12,:] - urows(total_nodes)[13,:] 
---> [ 0. 0.] 

爲什麼它不起作用???我如何刪除這些重複的值?

一個問題....

說兩個值是「幾乎」等於(說x1和x2),有沒有什麼辦法來取代他們的方式,他們都等於????我想要的是用x1替換x2,如果它們「幾乎」相等。

+0

drop_duplicates *不*維持秩序,我不明白你在問什麼......是有可能降簡化這個問題? – 2013-05-02 10:59:22

+0

謝謝。我完全編輯並重新構思了這個問題。我意識到我錯誤地問了錯誤的東西。 – Oniropolo 2013-05-02 15:41:18

+0

我不知道熊貓,但是有可能a)條目在稍後的小數位不同,或者b)它們是兩個不同的列表(它們恰好具有相同的條目),它們的對象標識進行比較?如果兩者都不是這樣,請忽略我的評論... – 2013-05-02 15:50:42

回答

5

如果我複製粘貼在你的數據,我得到:

>>> df 
      0   1 
0 1.000000 1.000000 
1 1.122733 1.153222 
2 0.941207 0.778028 
3 0.843013 0.916605 
4 0.930963 1.213833 
5 0.843013 0.916605 
6 0.755064 1.079864 

>>> df.drop_duplicates() 
      0   1 
0 1.000000 1.000000 
1 1.122733 1.153222 
2 0.941207 0.778028 
3 0.843013 0.916605 
4 0.930963 1.213833 
6 0.755064 1.079864 

所以它實際上是刪除,你的問題是數組不是恰好等於(儘管他們的區別四捨五入爲0用於顯示)。

一種解決方法是對數據進行四捨五入,然而許多小數位適用於df.apply(np.round, args=[4])之類的內容,然後刪除重複項。如果你想保留原來的數據,但刪除重複的高達舍入的行,你可以使用像

df = df.ix[~df.apply(np.round, args=[4]).duplicated()] 

這裏是一個真正笨拙的方式做你的要求與設定nearly-相同的值是實際上等於:

grouped = df.groupby([df[i].round(4) for i in df.columns]) 
subbed = grouped.apply(lambda g: g.apply(lambda row: g.irow(0), axis=1)) 
subbed.drop_index(level=list(df.columns), drop=True, inplace=True) 

這重新排序數據幀,但你可以調用.sort(),讓他們回到原來的順序,如果你需要的。

說明:第一行使用groupby以四捨五入的值對數據幀進行分組。不幸的是,如果你給groupby一個函數,它將它應用到標籤而不是行(所以你也許可以做df.groupby(lambda k: np.round(df.ix[k], 4)),但也很糟糕)。

第二行使用groupby上的apply方法將近似重複行的數據幀g替換爲新的數據幀g.apply(lambda row: g.irow(0), axis=1)。它使用數據框上的apply方法將每一行替換爲組中的第一行。

然後結果看起來像

     0   1 
0  1       
0.7551 1.0799 6 0.755064 1.079864 
0.8430 0.9166 3 0.843013 0.916605 
       5 0.843013 0.916605 
0.9310 1.2138 4 0.930963 1.213833 
0.9412 0.7780 2 0.941207 0.778028 
1.0000 1.0000 0 1.000000 1.000000 
1.1227 1.1532 1 1.122733 1.153222 

其中groupby插入了舍入值作爲指標。然後reset_index行刪除這些列。

希望有一個比我更瞭解熊貓的人會走過去,展示如何更好地做到這一點。

+0

謝謝您的回答!當我正在嘗試你的答案時,我有另一個問題出現在我的腦海裏。如果x1和x2不完全相等,然後將x2更改爲x1,這可能嗎? – Oniropolo 2013-05-02 17:16:09

+0

你的意思是你想採用'df'並改變它,以便幾乎重複的東西不會被刪除,而是發生變化,所以它們實際上是重複的?我不知道如何做到這一點,而不是與'groupby'有什麼毛病。 – Dougal 2013-05-02 17:19:50

+0

是的是!我有可怕的舍入問題。我用它來生成圖中的節點,如果x1,x2不完全相等,networkx將它們識別爲不同的節點,如果x1 = x2,我得到一個重組樹,這正是我想要的。我可以用一個簡單的if來實現這個,但是運行時間是O(N^2),它會毀掉所有的東西。也許我應該把它作爲一個新問題發佈...... – Oniropolo 2013-05-02 17:23:52

1

到@Dougal答案相似,但略有不同的方式

In [20]: df.ix[~(df*1e6).astype('int64').duplicated(cols=[0])] 
Out[20]: 
      0   1 
0 1.000000 1.000000 
1 1.122733 1.153222 
2 0.941207 0.778028 
3 0.843013 0.916605 
4 0.930963 1.213833 
6 0.755064 1.079864 
+0

謝謝你的回答!沒有四捨五入的權利?你只是改變了數據類型? – Oniropolo 2013-05-02 17:17:13

+0

@MiguelHerschberg乘以一百萬,然後投射到一個等於(幾乎)相同的東西,舍入到小數點後6位;不同之處在於它總是向下舍入。 – Dougal 2013-05-02 17:19:29

+0

約定....這是更多的截斷在0,而不是一個明確的四捨五入 – Jeff 2013-05-02 17:28:15