在Python Pandas数据框中删除重复项不删除重复项

2024-05-02 07:57:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我在删除副本时遇到问题。我的程序是基于一个循环来生成元组(x,y),然后将元组用作图中的节点。最终的节点阵列/矩阵为:

[[ 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,如果它们“接近”相等的话。


Tags: truedf节点副本etcarraydroptotal
2条回答

如果我复制粘贴到你的数据中,我会得到:

>>> 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()]

这里有一个非常笨拙的方法来实现您的要求:将几乎相等的值设置为实际相等:

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一个函数,它会把它应用到标签而不是行(所以你可以做df.groupby(lambda k: np.round(df.ix[k], 4)),但这也很糟糕)。

第二行使用groupby上的apply方法将几乎重复行的数据帧g替换为新的数据帧g.apply(lambda row: g.irow(0), axis=1)。使用dataframes上的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行删除这些列。

希望比我更了解熊猫的人能来看看如何做得更好。

类似于@Dougal answer,但方式略有不同

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

相关问题 更多 >