Pandas - 删除重复项后保留第一个值

9
我熟悉如何删除重复行,并使用参数firstlastnone。这并不太复杂,有大量的示例(例如这里)。
但是,我想找的是一种方法,可以找到重复项,但不是删除所有重复项并保留第一个,而是如果我有重复项,则保留所有重复项,但删除第一个:
因此,我想要的不是“删除重复项,保留第一个”,而是“保留重复项,删除第一个”。
例如:
给定这个数据框,在cost列中查找重复项:
    ID name type cost
0    0    a   bb    1
1    1    a   cc    2 <--- there are duplicates, so drop this row
2  1_0    a   dd    2
3    2    a   ee    3 <--- there are duplicates, so drop this row
4  2_0    a   ff    3
5  2_1    a   gg    3
6  2_2    a   hh    3

如果在cost列中存在重复值,则只需删除第一次出现的值,但保留其余值。
因此,我的输出应为:
    ID name type cost
0    0    a   bb    1
2  1_0    a   dd    2
4  2_0    a   ff    3
5  2_1    a   gg    3
6  2_2    a   hh    3

以下是示例数据框:

import pandas as pd

df = pd.DataFrame([
['0',   'a',    'bb',   '1'],
['1',   'a',    'cc',   '2'],
['1_0', 'a',    'dd',   '2'],
['2',   'a',    'ee',   '3'],
['2_0', 'a',    'ff',   '3'],
['2_1', 'a',    'gg',   '3'],
['2_2', 'a',    'hh',   '3']], columns = ['ID', 'name', 'type', 'cost'])
4个回答

8

您可以通过按位OR连接使用DataFrame.duplicated创建的2个掩码,并通过布尔索引进行过滤:

df = df[df.duplicated('cost') | ~df.duplicated('cost', keep=False)]
print (df)
    ID name type cost
0    0    a   bb    1
2  1_0    a   dd    2
4  2_0    a   ff    3
5  2_1    a   gg    3
6  2_2    a   hh    3

详情:

print (df.assign(mask1=df.duplicated('cost'), mask2=~df.duplicated('cost', keep=False)))
    ID name type cost  mask1  mask2
0    0    a   bb    1  False   True
1    1    a   cc    2  False  False
2  1_0    a   dd    2   True  False
3    2    a   ee    3  False  False
4  2_0    a   ff    3   True  False
5  2_1    a   gg    3   True  False
6  2_2    a   hh    3   True  False

1
啊,好的。那么它就会删除所有两个条件都为False的行。明白了。 - chitown88
我不确定,但我认为这应该是 df[~df.duplicated('cost') & df.duplicated('cost', keep=False)]。这实现了问题:“保留所有重复项,但不保留第一个实例”。 - defraggled

2
你可以使用 `groupby` 并传递一个 lambda 函数来获取重复记录之后的记录(如果存在重复记录):
``` 你可以使用 `groupby` 并传递一个 lambda 函数来获取重复记录之后的记录(如果存在重复记录): ```
>>> df.groupby('cost').apply(lambda group: group.iloc[1:] if len(group) > 1 else group).reset_index(drop=True)
    ID  cost name type
0    0     1    a   bb
1  1_0     2    a   dd
2  2_0     3    a   ff
3  2_1     3    a   gg
4  2_2     3    a   hh

对于更多自定义情况,如果您想仅保留组的特定成员(通过修改 group.iloc 切片),这将非常有帮助。 - irene

1
您可以使用异或(^)运算符执行以下操作,该运算符查找两个条件都为True的情况。由于我们使用NOT(~)运算符。它寻找相反的情况,例如:两者都为False:
df[~(df.cost.duplicated(keep=False) ^ df.cost.duplicated())]

输出

    ID name type cost
0    0    a   bb    1
2  1_0    a   dd    2
4  2_0    a   ff    3
5  2_1    a   gg    3
6  2_2    a   hh    3

1
您可以使用以下代码:

# Import pandas library 
import pandas as pd 

# initialize list of lists so i can create duplicate datas
data = [['tom', 10], ['nick', 15], ['juli', 14], ['nick', 15], ['julia', 140],
        ['tom', 10],['tom', 10],['tom', 10]] 

# Create the pandas DataFrame 
df = pd.DataFrame(data, columns = ['Name', 'Age']) 

# print dataframe. 
print(df)

# Now the logic begins from here

colnames=[]

for col in df.columns:
    colnames.append(col)


listdf=df.values.tolist()
temp=[]

for i in range(0,len(listdf)):
    if(listdf.count(listdf[i])>1 and listdf[i] not in temp):
        temp.append(listdf[i])

df = pd.DataFrame(temp, columns =colnames)

print("dataframe with only duplciates ")
print(df)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接