Python 从pandas.DataFrame删除所有重复项的更好策略?

Python 从pandas.DataFrame删除所有重复项的更好策略?,python,pandas,dataframe,Python,Pandas,Dataframe,有谁知道一个更好的策略,如何从pandas.DataFrame中删除所有的副本吗 我知道df.drop_duplicates(),请参见下面的示例: In [340]: import pandas as pd, string, random In [341]: a = [''.join([random.choice(string.ascii_letters+string.digits) for _ in range(4)]) for _ in range(5)] In [342]: b =

有谁知道一个更好的策略,如何从
pandas.DataFrame
中删除所有的
副本吗

我知道df.drop_duplicates()
,请参见下面的示例:

In [340]: import pandas as pd, string, random

In [341]: a = [''.join([random.choice(string.ascii_letters+string.digits) for _ in range(4)]) for _ in range(5)]

In [342]: b = [''.join([random.choice(string.digits) for _ in range(4)]) for i in range(5)]

In [343]: df1 = pd.DataFrame([a,b],index=list('ab')).T

In [344]: df1 = df1.append(df1.loc[1:3,:])

In [345]: df1.index = range(len(df1))

In [346]: df1 = df1.append(df1.loc[1:3,:])

In [347]: df1
Out[347]: 
      a     b
0  r4fb  4179
1  sv5e  8092
2  Oyeh  8788
3  fAdu  4018
4  PxKX  2818
5  sv5e  8092
6  Oyeh  8788
7  fAdu  4018
1  sv5e  8092
2  Oyeh  8788
3  fAdu  4018

In [348]: df1.drop_duplicates()
Out[348]: 
      a     b
0  r4fb  4179
1  sv5e  8092
2  Oyeh  8788
3  fAdu  4018
4  PxKX  2818
请注意,这不会删除所有的重复项,也就是说,它会删除下一个非唯一行,但保留原始行不变

我目前的策略和预期结果如下:

In [349]: same_first = df1.duplicated(subset=['a','b'])

In [350]: same_last = df1.duplicated(subset=['a','b'], take_last=True)

In [351]: rm_lst = ~(same_first|same_last)

In [352]: df1[rm_lst]
Out[352]: 
      a     b
0  r4fb  4179
4  PxKX  2818
请注意,现在只有真正的
unique
行未被触及

有没有更好的方法来获得同样的结果,也许是我错过的一条


谢谢。

这在一行中完成,但可读性不强,基本上它测试每列的值计数是否等于1,过滤结果列表并将索引用作布尔索引:

In [260]:

df1[df1.a.isin((df1.a.value_counts()[df1.a.value_counts() == 1]).index) & (df1.b.isin((df1.b.value_counts()[df1.b.value_counts() == 1]).index))]
Out[260]:
      a     b
0  mlmv  3869
4  LPNz  4109
分解此项将逐个语句显示正在发生的情况:

In [261]:
# gengerate a series of the value counts
df1.a.value_counts()

Out[261]:
qPyr    3
ms7I    3
aOuL    3
LPNz    1
mlmv    1
dtype: int64

In [262]:
# we are only interested in the ones that have a unique value, this generates a boolean index we can use to index into the above series
df1.a.value_counts()[df1.a.value_counts() == 1]

Out[262]:
LPNz    1
mlmv    1
dtype: int64

In [264]:
# now use isin on the the result above, but we compare the values against the index of the result above
df1.a.isin((df1.a.value_counts()[df1.a.value_counts() == 1]).index)
Out[264]:
0     True
1    False
2    False
3    False
4     True
5    False
6    False
7    False
1    False
2    False
3    False
Name: a, dtype: bool

所以你们只想在a和b都是重复的地方删除,在“a”中有重复的地方,在“b”中也有重复的地方,这是真的吗?我只是想复制
drop\u duplicates
的行为,除了原始行也应该被删除。有时两列可能包含相同的数据,有时不包含。我认为我的答案应该处理这个问题,因为它分别处理两列。我不能接受你的答案,因为它看起来更复杂,所以我决不会称之为“更好的策略”。此外,它似乎会花费更多的处理能力,因为在您的示例中,您分6个步骤过滤列:
value\u counts()->value\u counts()==1->df1.\uu getitem\uuuU()->index->isin()->df1.\uuuuu getitem\uUuUuUuUuUu()
,并且它仅用于一列。我最初的策略只需4个步骤即可完成:
duplicated()->duplicated()->comparison->df1.uu getitem_uuuuuuuuuo()
,并且它包含任意数量的列,我也可以作为一行代码编写:
df1[~(df1.duplicated(subset=['a','b'])df1.duplicated(subset=['a','b'],take\last=True))
。不过,感谢您对替代方法的全面解释。感谢您的努力。如果我错了,请纠正我,似乎你的
(df1.a.value\u counts()[df1.a.value\u counts()=1]).index)和(df1.b.isin((df1.b.value\u counts()[df1.b.value\u counts()=1]).index)
做的工作与我原来的
rm lst=~(先相同,后相同)
但在更复杂的问题上?@Narūnas是的,它看起来更复杂,这只是另一种方法,但它更明确一点,因为您正在寻找
df1.a.value_counts()==1
提供给您的唯一值