Python 使用pandas按列分组,然后根据条件创建新列

Python 使用pandas按列分组,然后根据条件创建新列,python,sql,pandas,lambda,pandas-groupby,Python,Sql,Pandas,Lambda,Pandas Groupby,我需要用pandas重现SQL如此简单的功能: select del_month , sum(case when off0_on1 = 1 then 1 else 0 end) as on1 , sum(case when off0_on1 = 0 then 1 else 0 end) as off0 from a1 group by del_month order by del_month 下面是一个示例性数据框架: a1 = pd.DataFrame({'del_m

我需要用pandas重现SQL如此简单的功能:

select
    del_month
    , sum(case when off0_on1 = 1 then 1 else 0 end) as on1
    , sum(case when off0_on1 = 0 then 1 else 0 end) as off0
from a1
group by del_month
order by del_month
下面是一个示例性数据框架:

a1 = pd.DataFrame({'del_month':[1,1,1,1,2,2,2,2], 'off0_on1':[0,0,1,1,0,1,1,1]})
下面是我用pandas复制上述SQL的尝试。第一行是有效的。第二行给出了一个错误:

a1['on1'] = a1.groupby('del_month')['off0_on1'].transform(sum)
a1['off0'] = a1.groupby('del_month')['off0_on1'].transform(sum(lambda x: 1 if x == 0 else 0))
下面是第二行的错误:

TypeError: 'function' object is not iterable
这与lambda函数有一个问题,这个问题已经解决了。更大的问题是如何在分组数据上复制SQL的sumcase逻辑。我正在寻找一个通用的解决方案,因为我需要经常做这种事情。我上一个问题中的答案建议在lambda函数中使用map,但是下面关于off0列的结果不是我需要的。on1列就是我想要的。对于整个组,即del_月,答案应相同


只需将条件逻辑表达式中的True求和:

import pandas as pd

a1 = pd.DataFrame({'del_month':[1,1,1,1,2,2,2,2], 
                   'off0_on1':[0,0,1,1,0,1,1,1]})

a1['on1'] = a1.groupby('del_month')['off0_on1'].transform(lambda x: sum(x==1))    
a1['off0'] = a1.groupby('del_month')['off0_on1'].transform(lambda x: sum(x==0))

print(a1)    
#    del_month  off0_on1  on1  off0
# 0          1         0    2     2
# 1          1         0    2     2
# 2          1         1    2     2
# 3          1         1    2     2
# 4          2         0    3     1
# 5          2         1    3     1
# 6          2         1    3     1
# 7          2         1    3     1
类似地,如果方言支持SQL,您也可以在SQL中执行同样的操作,而大多数方言应该:

选择 德鲁月 ,sumoff 0_on1=1作为on1 ,sumoff0_on1=0作为off0 来自a1 按德鲁月分组 德鲁月订单 要在pandas中复制上述SQL,请不要使用transform,而是在groupby.apply调用中发送多个聚合:


只需将条件逻辑表达式中的True求和:

import pandas as pd

a1 = pd.DataFrame({'del_month':[1,1,1,1,2,2,2,2], 
                   'off0_on1':[0,0,1,1,0,1,1,1]})

a1['on1'] = a1.groupby('del_month')['off0_on1'].transform(lambda x: sum(x==1))    
a1['off0'] = a1.groupby('del_month')['off0_on1'].transform(lambda x: sum(x==0))

print(a1)    
#    del_month  off0_on1  on1  off0
# 0          1         0    2     2
# 1          1         0    2     2
# 2          1         1    2     2
# 3          1         1    2     2
# 4          2         0    3     1
# 5          2         1    3     1
# 6          2         1    3     1
# 7          2         1    3     1
类似地,如果方言支持SQL,您也可以在SQL中执行同样的操作,而大多数方言应该:

选择 德鲁月 ,sumoff 0_on1=1作为on1 ,sumoff0_on1=0作为off0 来自a1 按德鲁月分组 德鲁月订单 要在pandas中复制上述SQL,请不要使用transform,而是在groupby.apply调用中发送多个聚合:

使用get_假人只需要一个groupby调用,这更简单

v = pd.get_dummies(df.pop('off0_on1')).groupby(df.del_month).transform(sum)
df = pd.concat([df, v.rename({0: 'off0', 1: 'on1'}, axis=1)], axis=1)

df
   del_month  off0  on1
0          1     2    2
1          1     2    2
2          1     2    2
3          1     2    2
4          2     1    3
5          2     1    3
6          2     1    3
7          2     1    3
此外,对于聚合,直接调用sum而不是使用apply:

使用get_假人只需要一个groupby调用,这更简单

v = pd.get_dummies(df.pop('off0_on1')).groupby(df.del_month).transform(sum)
df = pd.concat([df, v.rename({0: 'off0', 1: 'on1'}, axis=1)], axis=1)

df
   del_month  off0  on1
0          1     2    2
1          1     2    2
2          1     2    2
3          1     2    2
4          2     1    3
5          2     1    3
6          2     1    3
7          2     1    3
此外,对于聚合,直接调用sum而不是使用apply:


美丽的这正是我想要的。非常感谢!现在有没有一种方法可以像SQL示例代码中那样,在不链接另一个groupby的情况下折叠Delu month?很高兴听到这个消息!要折叠Delu month,请不要使用用于内联聚合的transform,而只在groupby上运行多个聚合。您介意为我键入一个示例吗?我会投赞成票的。谢谢。我是新来的美丽的这正是我想要的。非常感谢!现在有没有一种方法可以像SQL示例代码中那样,在不链接另一个groupby的情况下折叠Delu month?很高兴听到这个消息!要折叠Delu month,请不要使用用于内联聚合的transform,而只在groupby上运行多个聚合。您介意为我键入一个示例吗?我会投赞成票的。谢谢。我是新来的非常有趣的解决方案。你很有创造力。不确定这是否和@Parfait的解决方案一样具有普遍性,但我肯定会认真考虑一下。另外,我是个新手,所以我不知道哪一个更好P@Sean_Calgary您可以使用str.get_dummies将off_on列转换为一个数据帧,该数据帧由一个热编码的2列组成,然后将这些列相加。。。这与冻糕完全相同,但只需一个groupby即可完成。第二行只是做一些整理工作来获取列名。如果你想知道哪一个更好,我建议在你的数据上运行这两种解决方案,然后使用对你更有效的方法。你们真是太棒了。这是一个如此优雅和创造性的解决方案。你的智商一定是170!我不确定我是否可以在所有可以使用applycustom_函数的情况下使用pd.get_假人,但也许我只需要尝试一下并仔细考虑一下。好极了@肖恩·卡尔加里还没到那一步,不过还是欢迎你。非常有趣的解决方案。你很有创造力。不确定这是否和@Parfait的解决方案一样具有普遍性,但我肯定会认真考虑一下。另外,我是个新手,所以我不知道哪一个更好P@Sean_Calgary您可以使用str.get_dummies将off_on列转换为一个数据帧,该数据帧由一个热编码的2列组成,然后将这些列相加。。。这与冻糕完全相同,但只需一个groupby即可完成。第二行只是做一些整理工作来获取列名。如果你想知道哪一个更好,我建议在你的数据上运行这两种解决方案,然后使用对你更有效的方法。你们真是太棒了。这是一个如此优雅和创造性的解决方案。你的智商一定是170!我不确定我是否可以在所有可以使用applycustom_函数的情况下使用pd.get_假人,但也许我只需要尝试一下并仔细考虑一下。好极了@肖恩·卡尔加里还没到那里,不过还是欢迎你。