【问题标题】:Create new column in data.frame based on if-else assessment of other columns根据其他列的 if-else 评估在 data.frame 中创建新列
【发布时间】:2019-11-08 15:49:56
【问题描述】:

我正在尝试向我的数据框中添加一个新列 (x_new),该列取决于“定义”列中给出的值。定义列 x_definition 包含以下记录类型之一: - 一个常数 - 描述所需操作的字符串 - 不适用

我希望生成的列 x_new 如下所示: - 如果 x_definition 是 NA,那么 x_new 仍然是 NA。 - 如果x_definition 是一个字符串,那么它需要一定的计算。例如,如果它是'equal_to_z',那么结果应该是z,或者如果它的'third_of_z',那么x_new 应该是z/3。除了这些定义之外,还有更多的定义表明需要更复杂的 z 函数。 - 如果x_definition 是任何数字,那么x_new 应该就是那个数字。

我编写了以下代码来处理这些情况,但它是一组繁琐的嵌套ifelse 语句。我正在寻找一种方法,

data <- data %>% mutate(x_new = ifelse(
  is.na(x_definition), NA, ifelse(
    x_definition=='equal_to_z', z, ifelse(
      x_definition=='third_of_z', z/3, NA
      )
    )
  )
)

我也考虑过使用switch,但遇到了我不知道如何说“如果是数字,请保留为数字”的问题

a <- data %>% mutate(x_new = switch(x_definition,
  'equal_to_z' = z,
  'third_of_z' = z / 3,
  <number???> = x_definition
  )
)

解决这个问题的适当流程是什么?

【问题讨论】:

    标签: r dataframe if-statement switch-statement


    【解决方案1】:

    我认为case_when 正是您想要的。

    data = data %>%
        mutate(x_new = case_when(is.na(x_definition) ~ NA,
                                 x_definition == 'equal_to_z' ~ z,
                                 x_definition == 'third_of_z' ~ z / 3,
                                 !is.na(as.numeric(x_definition)) ~ as.numeric(x_definition)))
    

    【讨论】:

      【解决方案2】:

      是的,这是一个非常普遍的需求,它有一个很好的解决方案。

      你的逻辑是:

      如果 x_definition 为 NA,则 x_new 仍为 NA。 - 如果 x_definition 是一个字符串,那么它需要一定的计算。例如,如果它是“equal_to_z”而不是结果应该是 z,或者如果它是“third_of_z”,那么 x_new 应该是 z/3。除了这些定义之外,还有更多的定义表明需要更复杂的 z 函数。 - 如果 x_definition 是任何数字,那么 x_new 应该就是那个数字。

      我可以改写成

      np.nan if row['x_definition'] is np.nan 
      else row['z'] if row['x_definition'] == 'equal_to_z' 
      else row['z']/3 if row['x_definition'] == 'third_of_z' 
      else row['x_definition'] if isinstance('row['x_definition'], int) 
      else np.nan
      

      那你就可以了

      df['x_new'] = df.apply(lambda row: np.nan if row['x_definition'] is np.nan 
                          else row['z'] if row['x_definition'] == 'equal_to_z' 
                          else row['z']/3 if row['x_definition'] == 'third_of_z' 
                          else row['x_definition'] if isinstance('row['x_definition'], int) 
                          else np.nan, axis=1)
      

      或者如果你想更优雅

      def logic_for_x_new(row):
       ...
       return x_new
      
      df['x_new'] = df.apply(logic_for_x_new, axis=1)
      

      请注意在 Pandas 中检查 nan 的方式,我使用当 x 为 NaN 时 x==x 为 false 的技巧(请注意这一点)

      【讨论】:

      • 在 .apply() 中使用 axis=1 使得函数被逐行应用,每一行基本上是一个按列名索引的字典。
      猜你喜欢
      • 2019-09-30
      • 2019-09-28
      • 2014-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      相关资源
      最近更新 更多