根据其他列的if-else评估在data.frame中创建新列

时间:2019-11-08 15:49:56

标签: r dataframe if-statement switch-statement

我试图向我的数据框中添加一个新列(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
  )
)

解决这个问题的合适程序是什么?

2 个答案:

答案 0 :(得分: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)))

答案 1 :(得分:0)

是的,这是非常普遍的需求,并且有很好的解决方案。

您的逻辑是:

如果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)

请小心在熊猫中检查nan的技巧,当x为NaN时,我会使用x == x为假的技巧(请注意这一点)