【问题标题】:case_when function from R to Python从 R 到 Python 的 case_when 函数
【发布时间】:2019-07-06 07:02:03
【问题描述】:

如何在 python 代码中实现 R 的 case_when 函数?

这里是 R 的 case_when 函数:

https://www.rdocumentation.org/packages/dplyr/versions/0.7.8/topics/case_when

作为一个最低限度的工作示例,假设我们有以下数据框(python 代码如下):

import pandas as pd
import numpy as np

data = {'name': ['Jason', 'Molly', 'Tina', 'Jake', 'Amy'], 
        'age': [42, 52, 36, 24, 73], 
        'preTestScore': [4, 24, 31, 2, 3],
        'postTestScore': [25, 94, 57, 62, 70]}
df = pd.DataFrame(data, columns = ['name', 'age', 'preTestScore', 'postTestScore'])
df

假设我们想要创建一个名为“elderly”的新列,它查看“age”列并执行以下操作:

if age < 10 then baby
 if age >= 10 and age < 20 then kid 
if age >=20 and age < 30 then young 
if age >= 30 and age < 50 then mature 
if age >= 50 then grandpa 

有人可以帮忙吗?

【问题讨论】:

    标签: python pandas dataframe data-analysis


    【解决方案1】:

    你想使用np.select:

    conditions = [
        (df["age"].lt(10)),
        (df["age"].ge(10) & df["age"].lt(20)),
        (df["age"].ge(20) & df["age"].lt(30)),
        (df["age"].ge(30) & df["age"].lt(50)),
        (df["age"].ge(50)),
    ]
    choices = ["baby", "kid", "young", "mature", "grandpa"]
    
    df["elderly"] = np.select(conditions, choices)
    
    # Results in:
    #      name  age  preTestScore  postTestScore  elderly
    #  0  Jason   42             4             25   mature
    #  1  Molly   52            24             94  grandpa
    #  2   Tina   36            31             57   mature
    #  3   Jake   24             2             62    young
    #  4    Amy   73             3             70  grandpa
    

    conditionschoices 列表的长度必须相同。
    还有一个default 参数,当所有conditions 评估为False 时使用。

    【讨论】:

    • 谢谢,如果在条件下想要字符串而不是数值怎么办。例如,如果 age == "fourty" 那么 'marure'。 `' 如何修改你的代码?
    • 然后我会使用df[“age”].eq(“fourty”),因为这允许我们继续使用按位的&amp;
    • 如何修改代码以将所有其他情况置于一种条件下?例如,“大于 50”条件本质上是多余的。因此,拥有最后一个条件可能是更好的做法:“除了爷爷之外的其他任何东西”。
    • np.select 上有一个default 参数,当所有条件评估为False 时使用此参数:np.select(conditions, choices, default='Grandpa')。然后,您可以从 conditionschoices 列表中删除最后一个元素。
    【解决方案2】:

    np.select 很棒,因为它是一种根据条件为选择列表中的元素赋值的通用方法。

    但是,对于 OP 试图解决的特定问题,有一种简洁的方法可以实现与 pandas 的 cut method 相同的效果。

    
    bin_cond = [-np.inf, 10, 20, 30, 50, np.inf]            # think of them as bin edges
    bin_lab = ["baby", "kid", "young", "mature", "grandpa"] # the length needs to be len(bin_cond) - 1
    df["elderly2"] = pd.cut(df["age"], bins=bin_cond, labels=bin_lab)
    
    #     name  age  preTestScore  postTestScore  elderly elderly2
    # 0  Jason   42             4             25   mature   mature
    # 1  Molly   52            24             94  grandpa  grandpa
    # 2   Tina   36            31             57   mature   mature
    # 3   Jake   24             2             62    young    young
    # 4    Amy   73             3             70  grandpa  grandpa
    

    【讨论】:

      【解决方案3】:

      pyjanitordev 中有一个case_when 实现,在这种情况下可能会有所帮助,实现思想的灵感来自pydatatable 中的if_else 和R 的data.table 中的fcase;在引擎盖下,它使用pd.Series.mask:

      # pip install git+https://github.com/pyjanitor-devs/pyjanitor.git
      import pandas as pd
      import janitor as jn
      
      df.case_when(
      df.age.lt(10), 'baby', # 1st condition, result
      df.age.between(10, 20, 'left'), 'kid', # 2nd condition, result
      df.age.between(20, 30, 'left'), 'young', # 3rd condition, result
       df.age.between(30, 50, 'left'), 'mature', # 4th condition, result
      'grandpa',  # default if none of the conditions match
       column_name = 'elderly') # column name to assign to
       
          name  age  preTestScore  postTestScore  elderly
      0  Jason   42             4             25   mature
      1  Molly   52            24             94  grandpa
      2   Tina   36            31             57   mature
      3   Jake   24             2             62    young
      4    Amy   73             3             70  grandpa
      

      Alby's 解决方案对于这个用例来说比 if/else 结构更有效。

      【讨论】:

        猜你喜欢
        • 2023-01-05
        • 2018-12-31
        • 2018-11-08
        • 2021-09-05
        • 2022-01-02
        • 2020-08-19
        • 1970-01-01
        • 1970-01-01
        • 2022-01-11
        相关资源
        最近更新 更多