【问题标题】:Pandas Apply with condition熊猫有条件申请
【发布时间】:2019-03-19 10:47:40
【问题描述】:

我的客户副本具有不同的状态,因为每个客户订阅/产品都有一行。我想为客户生成一个new_status,并且要“取消”它,每个订阅状态都必须一起“取消”。

我用过:

df['duplicated'] = df.groupby('customer', as_index=False)['customer'].cumcount()

分隔索引中的每个重复项以指示重复值

Customer | Status | new_status | duplicated
 X       |canceled|            | 0
 X       |canceled|            | 1
 X       |active  |            | 2
 Y       |canceled|            | 0
 A       |canceled|            | 0
 A       |canceled|            | 1
 B       |active  |            | 0
 B       |canceled|            | 1

因此,我想使用 .apply 和/或 .loc 来生成:

Customer | Status | new_status | duplicated
 X       |canceled|            | 0
 X       |canceled|            | 1
 X       |active  |            | 2
 Y       |canceled|            | 0
 A       |canceled| canceled   | 0
 A       |canceled| canceled   | 1
 B       |active  |            | 0
 B       |canceled|            | 1

【问题讨论】:

  • Y 没有重复,但必须取消。公式可以包含或不包含唯一值
  • 性能重要吗?

标签: python pandas apply pandas-loc


【解决方案1】:

比较Series.eq 列的== 并使用GroupBy.transformGroupBy.all 来检查每个组的所有值是否都是Trues,然后比较Customer by Series.duplicatedkeep=False 以返回所有的骗子。最后按位AND (&) 链接在一起,并通过numpy.where 设置值:

m1 = df['Status'].eq('canceled').groupby(df['Customer']).transform('all')
m2 = df['Customer'].duplicated(keep=False)

df['new_status'] = np.where(m1 & m2, 'cancelled', '')
print (df)
  Customer    Status new_status  duplicated
0        X  canceled                      0
1        X  canceled                      1
2        X    active                      2
3        Y  canceled                      0
4        A  canceled  cancelled           0
5        A  canceled  cancelled           1
6        B    active                      0
7        B  canceled                      1

【讨论】:

  • 非常感谢。我不太了解 .transform 和 .eq 方法
  • @RicardoFernandes - 是的,它是由 Series - docs 分组的。顺便说一句,两种解决方案都是正确的。如果我或其他答案有帮助,请不要忘记accept。谢谢。
【解决方案2】:

据我了解,您可以尝试这样做:

df['new_status']=(df.groupby('Customer')['Status'].
  transform(lambda x: x.eq('canceled').all()).map({True:'cancelled'})).fillna(df.new_status)
print(df)

    Customer    Status new_status  duplicated
0   X         canceled             0         
1   X         canceled             1         
2   X         active               2         
3   Y         canceled  cancelled  0         
4   A         canceled  cancelled  0         
5   A         canceled  cancelled  1         
6   B         active               0         
7   B         canceled             1   

编辑,因为预期的 o/p 已更改:

df['new_status']=(df.groupby('Customer')['Status'].
             transform(lambda x: x.duplicated(keep=False)&(x.eq('canceled').all()))
                         .map({True:'cancelled',False:''}))
print(df)

  Customer    Status new_status  duplicated
0   X         canceled             0         
1   X         canceled             1         
2   X         active               2         
3   Y         canceled             0         
4   A         canceled  cancelled  0         
5   A         canceled  cancelled  1         
6   B         active               0         
7   B         canceled             1   

【讨论】:

  • 如果数据帧很大,applytransform 中的调用函数应该很慢。
  • 我认为如果没有必要。
  • 1800 列。我认为可以使用 .apply 并感谢我正在验证值,但看起来正确
  • 我编辑了帖子只是为了尽可能清楚,但第一个 o/p 更接近我想要的谢谢。我想更多地了解您是如何做到的以及何时使用 .map、.eq 和 .transform
  • @RicardoFernandes 没问题。所以x.eq('canceled').all() 检查状态中的所有分组项目是否等于取消,所以使用all() 返回true。而不是使用 map 将 true 替换为 1 并将 false 替换为空白。最好尝试删除代码的某些部分,我想你会理解的。 :) 如果有任何问题 lemme 知道。干杯..!!
猜你喜欢
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-11
  • 2020-12-01
  • 2022-01-16
  • 2017-01-30
相关资源
最近更新 更多