【问题标题】:Create new column based on multiple groupby conditions根据多个 groupby 条件创建新列
【发布时间】:2018-04-01 00:16:22
【问题描述】:

我想在这个 df 中创建一个具有以下条件的新列。 education 列是一个从 1 到 5 的分类值(1 是较低的教育水平,5 是较高的教育水平)。我想创建一个具有以下逻辑的函数(以便在 df 中创建一个新列)

首先,对于任何 id 检查是否至少有一个教育水平毕业,那么新列必须具有更高的教育水平毕业。

其次,如果某个特定 id 没有毕业教育水平(必须在“课程中”中具有所有教育水平)。所以,必须检查最高教育水平并减去一个。

df
id  education stage
1   2         Graduated
1   3         Graduated
1   4         In course
2   3         In course
3   2         Graduated
3   3         In course
4   2         In course

预期输出:

id  education stage       new_column
1   2         Graduated   3
1   3         Graduated   3
1   4         In course   3
2   3         In course   2
3   2         Graduated   2
3   3         In course   2
4   2         In course   1

【问题讨论】:

    标签: python python-3.x pandas numpy dataframe


    【解决方案1】:

    你可以这样做:

    import pandas as pd
    df = pd.DataFrame({'id': [1, 1, 1, 2, 3, 3, 4], 'education': [2, 3, 4, 3, 2, 3, 2],
                       'stage': ['Graduated', 'Graduated', 'In course', 'In course', 'Graduated', 'In course', 'In course']})
    
    
    max_gr = df[df.stage == 'Graduated'].groupby('id').education.max()
    max_ic = df[df.stage == 'In course'].groupby('id').education.max()
    
    # set all cells to the value from max_ed
    df['new_col'] = df.id.map(max_gr)
    # set cells that have not been filled to the value from max_ic - 1
    df.loc[df.new_col.isna(), ['new_col']] = df.id.map(max_ic - 1)
    

    series.map(other_series) 返回一个新系列,其中 series 中的值已被 other_series 中的值替换。

    【讨论】:

    • 是的,易于阅读。我赞成并发布了一个替代解决方案,我认为基于您的解决方案更具可读性。我最初将它放在您的解决方案中,但将其移出。很抱歉给您带来不便。
    • @AntonvBR 我同意,您的解决方案更易于阅读。我不知道 series.update()。
    【解决方案2】:

    这是一种方式。

    df['new'] = df.loc[df['stage'] == 'Graduated']\
                  .groupby('id')['education']\
                  .transform(max).astype(int)
    
    df['new'] = df['new'].fillna(df.loc[df['stage'] == 'InCourse']\
                                   .groupby('id')['education']\
                                   .transform(max).sub(1)).astype(int)
    

    结果

       id  education      stage  new
    0   1          2  Graduated    3
    1   1          3  Graduated    3
    2   1          4   InCourse    3
    3   2          3   InCourse    2
    4   3          2  Graduated    2
    5   3          3   InCourse    2
    6   4          2   InCourse    1
    

    说明

    • 首先,映射到按最大教育的 id 分组的“已毕业”数据集。
    • 其次,映射到“InCourse”数据集,按最大教育减去 1 的 id 分组。

    【讨论】:

      【解决方案3】:

      替代解决方案基于 Markus Löffler。

      max_ic = df[df.stage.eq('In course')].groupby('id').education.max() - 1
      max_gr = df[df.stage.eq('Graduated')].groupby('id').education.max()
      
      # Update with max_gr
      max_ic.update(max_gr)
      
      df['new_col'] = df.id.map(max_ic)
      

      【讨论】:

        猜你喜欢
        • 2021-06-11
        • 1970-01-01
        • 1970-01-01
        • 2020-07-11
        • 1970-01-01
        • 2020-09-12
        • 1970-01-01
        • 1970-01-01
        • 2022-07-12
        相关资源
        最近更新 更多