【问题标题】:Groupby count only when a certain value is present in one of the column in pandas仅当 Pandas 的一列中存在某个值时,Groupby 才计数
【发布时间】:2018-11-05 19:56:03
【问题描述】:

我有一个类似于下面提到的数据库的数据框:

+------------+-----+--------+ | time | id | status | +------------+-----+--------+ | 1451606400 | id1 | Yes | | 1451606400 | id1 | Yes | | 1456790400 | id2 | No | | 1456790400 | id2 | Yes | | 1456790400 | id2 | No | +------------+-----+--------+

我按上面提到的所有列进行分组,我可以使用以下命令成功地在名为 'count' 的不同列中获取计数:

df.groupby(['time','id', 'status']).size().reset_index(name='count')

但我希望上述数据框中的计数仅出现在带有status = 'Yes' 的行中,其余的应该是'0'

期望的输出:

+------------+-----+--------+---------+ | time | id | status | count | +------------+-----+--------+---------+ | 1451606400 | id1 | Yes | 2 | | 1456790400 | id2 | Yes | 1 | | 1456790400 | id2 | No | 0 | +------------+-----+--------+---------+

我尝试使用以下代码计算status = 'Yes'

df[df['status']== 'Yes'].groupby(['time','id','status']).size().reset_index(name='count')

这显然给了我那些带有status = 'Yes' 的行并丢弃了其余的行。我想要那些带有count = 0的废弃的

有没有办法得到结果?

提前致谢!

【问题讨论】:

    标签: python pandas dataframe pandas-groupby


    【解决方案1】:

    使用带有apply 的lambda 函数和计数sum boolena True 值过程,如1

    df1 = (df.groupby(['time','id','status'])
             .apply(lambda x: (x['status']== 'Yes').sum())
             .reset_index(name='count'))
    

    或创建新列并聚合sum

    df1 = (df.assign(A=df['status']=='Yes')
             .groupby(['time','id','status'])['A']
             .sum()
             .astype(int)
             .reset_index(name='count'))
    

    非常相似的解决方案,没有新列,但可读性差一点:

    df1 = ((df['status']=='Yes')
            .groupby([df['time'],df['id'],df['status']])
            .sum()
            .astype(int)
            .reset_index(name='count'))
    
    print (df)
             time   id status  count
    0  1451606400  id1    Yes      2
    1  1456790400  id2     No      0
    2  1456790400  id2    Yes      1
    

    【讨论】:

    • 嘿@jezrael,感谢您的回答......再次! :) 我继续使用第一个,它就像一个魅力。我会考虑其他解决方案,如果第一个解决方案效果不佳,我会尝试。
    • @ManikanthaNekkalapudi - 欢迎您!第二种解决方案在大 DataFrame 中应该会快一些。
    • 我无法在上述解决方案中应用转换来将结果推送到原始数据帧。具有上述条件的新列中的结果应该在原始数据框中,而不是由 groupby 生成的数据框。有什么办法吗?
    • @ManikanthaNekkalapudi - 你能解释更多吗?您是否需要原始列并通过输出数据创建新列?喜欢df['new'] = (df.assign(A=df['status']=='Yes') .groupby(['time','id','status'])['A'] .transform('sum') .astype(int) .reset_index(name='count'))
    • 是的,我想计算结果并将结果放回父数据框。另外,我正在尝试上述解决方案以获得结果,但在父数据框中没有得到正确的值。
    【解决方案2】:

    如果您不介意输出格式略有不同,可以pd.crosstab

    df = pd.DataFrame({'time': [1451606400]*2 + [1456790400]*3,
                       'id': ['id1']*2 + ['id2']*3,
                       'status': ['Yes', 'Yes', 'No', 'Yes', 'No']})
    
    res = pd.crosstab([df['time'], df['id']], df['status'])
    
    print(res)
    
    status          No  Yes
    time       id          
    1451606400 id1   0    2
    1456790400 id2   2    1
    

    结果是一种更有效存储数据的方式,因为您不会在每个“是”/“否”类别的单独行中重复索引。

    【讨论】:

    • 感谢您的回答!不幸的是,我对crosstab 不熟悉,但如果我找到任何需要的东西,我一定会留意这个答案。
    猜你喜欢
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-05
    • 1970-01-01
    • 2018-06-24
    • 2021-10-29
    • 1970-01-01
    相关资源
    最近更新 更多