Pandas - 与删除重复项相反,先保留
Pandas - Opposite of drop duplicates, keep first
我熟悉如何删除重复行,然后使用 first
、last
、none
的参数。没什么太复杂的,而且有很多例子(即here)。
但是,我正在寻找的是有一种方法可以找到重复项,但不是删除所有重复项并保留第一个,如果我有重复项,保留所有重复项但删除第一个:
所以我想要 "keep if duplicates, drop first"
而不是 "drop if duplicates, keep the first"
示例:
给定此数据框,并查看 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'])
您可以链接 DataFrame.duplicated
with bitwise OR
and filter by boolean indexing
创建的 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
您可以使用 XOR (^)
运算符执行以下操作,该运算符会查找两个条件都为真。由于我们使用 NOT (~)
运算符。它寻找相反的例子:both 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
如果存在欺骗,您可以使用 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
您可以使用以下代码:
# 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)
我熟悉如何删除重复行,然后使用 first
、last
、none
的参数。没什么太复杂的,而且有很多例子(即here)。
但是,我正在寻找的是有一种方法可以找到重复项,但不是删除所有重复项并保留第一个,如果我有重复项,保留所有重复项但删除第一个:
所以我想要 "keep if duplicates, drop first"
而不是 "drop if duplicates, keep the first"示例:
给定此数据框,并查看 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'])
您可以链接 DataFrame.duplicated
with bitwise OR
and filter by boolean indexing
创建的 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
您可以使用 XOR (^)
运算符执行以下操作,该运算符会查找两个条件都为真。由于我们使用 NOT (~)
运算符。它寻找相反的例子:both 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
如果存在欺骗,您可以使用 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
您可以使用以下代码:
# 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)