在 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筛选

将多个键上的 pandas 数据帧映射为列或 multiIndex

如何将 python 对象(如字典)分配给 pandas 列

Pandas:查找不在另一个DataFrame中的DataFrame行[重复]

Pandas:时间戳系列中的唯一天数

批量从Dataframe插入到DB,忽略Pyspark中的失败行