pandas 当与第1列核对时,识别并删除第2列中存在的重复项

o0lyfsai  于 2023-06-28  发布在  其他
关注(0)|答案(3)|浏览(116)

| ID| ab_keywords| bc_keywords|
| - -----|- -----|- -----|
| ABL345|锐龙,锐龙7 x,锐龙5800,锐龙7 x| Ryzen,Ryzen 71x,Ryzen 5900,best|
| ABL448| Ryzen 5800 7x,Ryzen 8x,cpu,Ryzen 5800| Ryzen 5900 71 x,Ryzen 8x,处理器,最佳|
这是一个表,我想识别并删除bc_keywords中存在的重复值, 如果这些值已经存在于列中:ab_keywords
例如:“ryzen”存在于ID的两列中:ABL 345,所以我想识别它并将其从bc_keywords中删除
所以我期望的表看起来像这样:
| ID| ab_keywords| bc_keywords|双曲|bc_new|
| - -----|- -----|- -----|- -----|- -----|
| ABL345|锐龙,锐龙7 x,锐龙5800,锐龙7 x| Ryzen,Ryzen 71x,Ryzen 5900,best|雷曾|ryzen 71x,ryzen 5900,best|
| ABL448| Ryzen 5800 7x,Ryzen 8x,cpu,Ryzen 5800| Ryzen 5900 71 x,Ryzen 8x,处理器,最佳|Ryzen 8x| Ryzen 5900 71 x,处理器,最佳|
有什么办法可以让我做吗?
列“duplis”也不是很需要,我的主要目标是删除duplis和添加新的关键字列表在一个新的列。
我试过使用df.duplicated(),但肯定像我做错了什么,并没有得到我正在寻找的答案
duplicated()只是给了我一个布尔序列列
我也尝试了以下方法:

dof['new'] = list(set(dof['bc']) - set(dof['ab']))
dof['new']
dof.head()

但是输出看起来很奇怪:
| ID| ab_keywords| bc_keywords| bc_new|
| - -----|- -----|- -----|- -----|
| ABL345|锐龙,锐龙7 x,锐龙5800,锐龙7 x| Ryzen,Ryzen 71x,Ryzen 5900,best| Ryzen 5900 71 x,Ryzen 8x,处理器,最佳|
| ABL448| Ryzen 5800 7x,Ryzen 8x,cpu,Ryzen 5800| Ryzen 5900 71 x,Ryzen 8x,处理器,最佳|Ryzen,Ryzen 71x,Ryzen 5900,best|

jgwigjjp

jgwigjjp1#

尝试:
1.按“,”拆分bc_keywords

  1. explode列,每个关键字得到一行
    1.识别重复项
  2. groupbyagg-根据需要注册
df["bc_keywords"] = df["bc_keywords"].str.split(",")
df = df.explode("bc_keywords")
duplicates = df.apply(lambda row: row["bc_keywords"] in row["ab_keywords"].split(","), axis=1)
df["bc_new"] = df["bc_keywords"].where(~duplicates)
df["duplis"] = df["bc_keywords"].where(duplicates)
output = df.groupby("ID").agg({"ab_keywords": "first", 
                               "bc_keywords": ",".join, 
                               "duplis": "first",
                               "bc_new": lambda x: ",".join(x.dropna())})

>>> output

| ID| ab_keywords| bc_keywords|双曲|bc_new|
| - -----|- -----|- -----|- -----|- -----|
| ABL345|锐龙,锐龙7 x,锐龙5800,锐龙7 x| Ryzen,Ryzen 71x,Ryzen 5900,best|雷曾|ryzen 71x,ryzen 5900,best|
| ABL448| Ryzen 5800 7x,Ryzen 8x,cpu,Ryzen 5800| Ryzen 5900 71 x,Ryzen 8x,处理器,最佳|Ryzen 8x| Ryzen 5900 71 x,处理器,最佳|

ugmeyewa

ugmeyewa2#

一个可能的解决方案是使用 helper funcdedupsplit构成的关键字:

from functools import partial

def sjoin(kws, sep=","):
    return sep.join(filter(None, kws))

def dedup(lst_ab, lst_bc):
    dups, new_bc = zip(
        *[(bc, None) if bc in lst_ab else (None, bc) for bc in lst_bc]
    )
    return sjoin(dups), sjoin(new_bc) # <-- add the sep(s) if needed

keywords = df[["ab_keywords", "bc_keywords"]].apply(lambda x: x.str.split(","), axis=1)

df["duplis"], df["new_bc"] = zip(
    *[dedup(lst_ab, lst_bc) for lst_ab, lst_bc in keywords.to_numpy()]
)

输出:
| ID| ab_keywords| bc_keywords|双曲|新bc|
| - -----|- -----|- -----|- -----|- -----|
| ABL345|锐龙,锐龙7 x,锐龙5800,锐龙7 x| Ryzen,Ryzen 71x,Ryzen 5900,best|雷曾|ryzen 71x,ryzen 5900,best|
| ABL448| Ryzen 5800 7x,Ryzen 8x,cpu,Ryzen 5800| Ryzen 5900 71 x,Ryzen 8x,处理器,最佳|Ryzen 8x| Ryzen 5900 71 x,处理器,最佳|

yshpjwxd

yshpjwxd3#

您应该将此逻辑应用于 Dataframe 中的每一行。
我根据你的例子创建了一个模拟数据集:

data = pd.DataFrame({
    "ab_keywords": ["aaa,bbb,ccc", "bbb,ccc,dd,eee"],
    "bc_keywords": ["bbb,ccc,rrr", "ccc,eee,fff,ggg"]
})

然后准备一个函数应用于每一行:

def remove_duplicates(row):
    return list(set(row['bc_keywords'].split(",")) - set(row['ab_keywords'].split(",")))

data["bc_new"] = data.apply(remove_duplicates, axis=1)
data

输出:

ab_keywords     bc_keywords     bc_new
0   aaa,bbb,ccc     bbb,ccc,rrr     [rrr]
1   bbb,ccc,dd,eee  ccc,eee,fff,ggg [fff, ggg]

如果值存储为字符串而不是列表,则在应用函数之前或在函数内部也应该将它们拆分为列表。
编辑:我更新了代码,将值作为字符串处理-添加了将它们首先拆分为列表。

相关问题