在 pandas df 中给出唯一键,其中行满足具有公共键的条件
Posted
技术标签:
【中文标题】在 pandas df 中给出唯一键,其中行满足具有公共键的条件【英文标题】:Give unique keys in a pandas df with rows that satisfy condition having common key 【发布时间】:2022-01-04 07:34:31 【问题描述】:我有一个这样的数据框:
d = 'id1':['3def','xyx1','roro','p344o','fjfje'],
'id2':['hhyy','drdr','xyx1','xyx1','xyx1']
,'score':[100,90,100,90,70]
df1 = pd.DataFrame(d)
df1
id1 id2 score
0 3def hhyy 100
1 xyx1 drdr 90
2 roro xyx1 100
3 p344o xyx1 90
4 fjfje xyx1 70
我的最终目标是为每一行提供一个唯一的键。问题是我希望 id1 等于 id2 并且得分超过 80 的行集具有一个公共键(在我的情况下为索引 1、2、3)。所以我希望我想要的结果是这样的:
id1 id2 score uid
0 3def hhyy 100 1
1 xyx1 drdr 90 2
2 roro xyx1 100 2
3 p344o xyx1 90 2
4 fjfje xyx1 70 3
我做了一些事情,但似乎没有成功:
msk = (((df1['id1'].isin(df1['id2']).shift(-1)) (df1['id2'].isin(df1['id2']).shift(-1))) &\
(df1['score'] > 80).shift(-1))
df1['uid'] = msk.cumsum()
print(df1)
id1 id2 score uid
0 3def hhyy 100 1
1 xyx1 drdr 90 2
2 roro xyx1 100 3
3 p344o xyx1 90 3
4 fjfje xyx1 70 3
任何有关如何解决此问题的帮助将不胜感激。
【问题讨论】:
在您的数据框中,我看到有多个 id2 实例。 id1也可以有多个实例吗? 不行,只能在id2中找到 我在您的示例中看不到任何行,其中id1
等于id2
。
我不太确定我是否遵循关于 uid 如何递增的逻辑。如果 id2 中的每个唯一值或分数小于 80,它会递增?
@Mortz 我已经有了。这是 order 中的第二个数据帧。我已经提供了它作为我想要的结果。
【参考方案1】:
您可以使用以下算法:
为每组 id1 创建一个 uid 将这些 uid 映射到 id2 的值上,如果分数符合标准,则替换 uid 最终通过减去额外的差异来修复非顺序 uid# step 1
df1['uid'] = df1.groupby('id1', sort=False).ngroup().add(1)
# step 2
alt_uid = df1['id2'].map(df1.set_index('id1')['uid']).convert_dtypes()
# step 3
df1['uid'] = df1['uid'].mask(df1['score'].gt(80) & alt_uid.notna(), alt_uid)
# final uid
df1['uid'] -= df1['uid'].diff().sub(1).fillna(0).clip(lower=0)
输出:
id1 id2 score uid
0 3def hhyy 100 1
1 xyx1 drdr 90 2
2 roro xyx1 100 2
3 p344o xyx1 90 2
4 fjfje xyx1 70 3
带有中间步骤的输出:
id1 id2 score uid uid_step1 uid_step2 uid_step3
0 3def hhyy 100 1 1 <NA> 1
1 xyx1 drdr 90 2 2 <NA> 2
2 roro xyx1 100 2 3 2 2
3 p344o xyx1 90 2 4 2 2
4 fjfje xyx1 70 3 5 2 5
【讨论】:
【参考方案2】:我认为创建自定义函数更容易:
def func(data):
idx, cur_id, cur_score, result = 0, None, None, []
for x, y, z in data.values:
if not ((cur_id == y) & (z > 80)):
cur_id, cur_score = x, z
idx += 1
result.append(idx)
return result
df["new"] = func(df)
print (df)
id1 id2 score new
0 3def hhyy 100 1
1 xyx1 drdr 90 2
2 roro xyx1 100 2
3 p344o xyx1 90 2
4 fjfje xyx1 70 3
【讨论】:
减 1,& 被滥用,他们不再推荐值以上是关于在 pandas df 中给出唯一键,其中行满足具有公共键的条件的主要内容,如果未能解决你的问题,请参考以下文章
将多个键上的 pandas 数据帧映射为列或 multiIndex
如何将 python 对象(如字典)分配给 pandas 列