2013-05-02 301 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