【问题标题】:groupby with conditions and classify python带条件的groupby并对python进行分类
【发布时间】:2021-04-06 23:03:25
【问题描述】:

我有 2 列(名称和 ID)的数据框。有成千上万的名字。但是每个名字,只有两个id(90和91,所以id列​​只包含90和91)。

示例数据框如下所示。

name    id
kevin   90
kevin   91
kevin   90
kevin   90
John    90
John    90
John    90
John    90
John    90
kevin   90
kevin   90
kevin   91
kevin   91

首先需要groupby使用 name 和 id 列并获取每个组合的计数

预期输出:

name    id  count
kevin   90  13
        91  2
elly    91  15
john    90  6
adam    90  3
        91  20
anjelo  90  12
        91  19

然后需要使用以下条件进行违规分类。

  1. 名称包含只有一个 id(90 或 91),它不违规(例如 elly 和 john 不是违规者)。

  2. 名称包含两个 id

    i.) 90:小于 5 和 91:任意数字(大于 0)>>>>>>> 不违规强>(例如:亚当)

    ii.) 所有其他 id 组合>>>>> 违规者(例如:kevin 和 anjelo)

最终预期的数据框:

name    violation
kevin     1
elly      0
john      0
adam      0
anjelo    1

我这样做的目的:

首先我使用 name 和 id 分组并获取每个组合的计数(但此方法不返回上面显示的数据帧。)

df.groupby(['name', 'id']).size().reset_index(name='counts')

在第二部分,我只知道如果 name 包含两个 ids(90 和 91),如何识别违规者。我不知道如何给已确定的违规者提供上述条件。

x = df.groupby('name').id.unique().reset_index()
x['Violation'] = x.id.apply(lambda x: 1 if (90, 91) in zip(x, x[1:]) else 0)
x.drop('id', 1, inplace=True)
x

非常感谢您的支持!!!!!!!!!!!!!!!

【问题讨论】:

    标签: python pandas dataframe classification pandas-groupby


    【解决方案1】:

    让我们尝试crosstab 和布尔掩码来定位违规者:

    # frequency table
    s = pd.crosstab(df['name'], df['id'])
    
    m1 = s.ne(0).sum(1).eq(1) # condition 1
    m2 = ~m1 & s[90].lt(5) & s[91].gt(0) # condition 2
    out = (~m1 & ~m2).view('i1').to_frame('violator') # violators
    

    详情:

    使用crosstab计算频率表:

    print(s)
            90  91
    adam     3  20
    anjelo  12  19
    elly     0  15
    john     6   0
    kevin   13   2
    

    创建表示条件的布尔掩码,其中名称仅包含一个 id(90 或 91)

    print(m1)
    name
    adam      False
    anjelo    False
    elly       True # -> Non violator
    john       True # -> Non violator
    kevin     False
    dtype: bool
    

    创建表示条件的布尔掩码,其中名称包含两个 id, 并且 90 的值小于 5 而 91 的值大于 0

    print(m2)
    name
    adam       True # -> Non violator
    anjelo    False
    elly      False
    john      False
    kevin     False
    dtype: bool
    

    结合condition 1condition 2 来获取违规者:

    print(out)
             violator
    name             
    adam            0
    anjelo          1
    elly            0
    john            0
    kevin           1
    

    【讨论】:

    • 非常感谢,伙计。从您的代码中学到了很多东西。
    • @kevin 很高兴我能帮上忙。
    【解决方案2】:

    您还可以尝试在分组步骤之后旋转数据框:

    import pandas as pd    
    pv=pd.pivot_table(df, values = 'counts', index=['name'], columns = 'id').reset_index().fillna(0)
    pv.columns = pv.columns.map(str)
    

    之后,您可以应用逻辑以获得您的违规标志:

    import numpy as np
    pv['violation'] = np.where((pv['90']==0) | (pv['91']==0) | (pv['90']<5) & (pv['91']>0),0,1)
    

    【讨论】:

      【解决方案3】:

      在获得 groupby 计数后,为什么不过滤掉 ID=90 和 count

      【讨论】:

        【解决方案4】:
        import numpy as np
        g=df.groupby(['name','id']).size().to_frame('count').reset_index()#Groupby to get dataframe with count
        
        #Allocate viloation
        g['violation']=np.where((~g.name.duplicated(keep=False))|(g.id.eq(90)&g['count'].le(5)|g.id.eq(91)&g['count'].gt(0)),0,1)
        print(g)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-07
          • 2020-12-03
          • 2017-02-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-24
          相关资源
          最近更新 更多