【问题标题】:Comparing rows of string inside groupby and assigning a value to a new column pandas比较 groupby 中的字符串行并将值分配给新列 pandas
【发布时间】:2021-04-09 08:19:20
【问题描述】:

我有一个员工数据集(他们的 ID)和他们老板的名字,这些年数年了。

df:

我需要做的是看看员工是否有老板的变化。所以,期望的输出是:

对于只在 df 中出现一次的员工,我只分配 0(没有老板的变动)。但是,对于在df工作了几年的员工,我不知道该怎么做。

我在想首先我需要为他们出现在df中的第一年分配0(因为我们不知道之前谁是老板,所以没有老板的变化)。然后我需要将老板的名字与下一行的名字进行比较,并决定将 1 或 0 分配到 ManagerChange 列中。

到目前为止,我将 df 一分为二(具有唯一 ID 和重复 ID),并将 0 分配给 ManagerChange 以获得唯一 ID。

然后我将重复的 ID 分组并按年份排序。但是,我是 Python 新手,无法弄清楚如何比较字符串并将结果值分配给 groupby 内的新列。请帮忙。

到目前为止我的代码:

# splitting database in two
bool_series = df["ID"].duplicated(keep=False)

df_duplicated=df[bool_series]

df_unique = df[~bool_series]

# assigning 0 for ManagerChange for the unique IDs
df_unique['ManagerChange'] = 0

# groupby by ID and sorting by year for the duplicated IDs
df_duplicated.groupby('ID').apply(lambda x: x.sort_values('Year'))

【问题讨论】:

    标签: python pandas pandas-groupby string-comparison


    【解决方案1】:

    您可以按shift() 分组并在Boss 列上进行比较。

    # Sort value first
    df.sort_values(['ID', 'Year'], inplace=True)
    
    # Compare Boss column with shifted Boss column
    df['ManagerChange'] = df.groupby('ID').apply(lambda group: group['Boss'] != group['Boss'].shift(1)).tolist()
    
    # Change True to 1, False to 0
    df['ManagerChange'] = df['ManagerChange'].map({True: 1, False: 0})
    
    # Sort df to original df
    df = df.sort_index()
    
    # Change the first in each group to 0
    df.loc[df.groupby('ID').head(1).index, 'ManagerChange'] = 0
    
    # print(df)
    
         ID  Year     Boss  ManagerChange
    0  1234  2018     Anna              0
    1   567  2019    Sarah              0
    2  1234  2020  Michael              0
    3  8976  2019     John              0
    4  1234  2019  Michael              1
    5  8976  2020     John              0
    

    您也可以使用fill_value 参数,这将帮助您摆脱最后的df.loc[] 操作。

    # Sort value first
    df.sort_values(['ID', 'Year'], inplace=True)
    
    df['ManagerChange'] = df.groupby('ID').apply(lambda group: group['Boss'] != group['Boss'].shift(1, fill_value=group['Boss'].iloc[0])).tolist()
    
    # Change True to 1, False to 0
    df['ManagerChange'] = df['ManagerChange'].map({True: 1, False: 0})
    
    # Sort df to original df
    df = df.sort_index()
    

    【讨论】:

    • 感谢您的回答!我在我的完整数据库上运行它,但结果好坏参半。对于发生 Manager Change 的 ID,结果是正确的。但是对于数据库中不止一次但没有经理更改的 ID(例如,我的示例中的 ID 8976),ManagerChange 中的值 1 仍分配给第一个外观(同一示例中的 2019 年)。请你告诉我为什么会这样?
    • @Kristina 你跑df.loc[df.groupby('ID').head(1).index, 'ManagerChange'] = 0了吗?
    • 是的,我做到了,它只对 df 中的 ID 有效
    • @Kristina 不知道为什么,因为它不会发生在您的给定数据中。
    • 可能是因为有一些额外的空格或其他我看不到的符号导致相同的名称不同吗?有没有办法将此检查合并到代码中?
    猜你喜欢
    • 1970-01-01
    • 2019-12-26
    • 2019-06-17
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    相关资源
    最近更新 更多