我试图向我的数据框中添加一个新列(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
)
)
解决这个问题的合适程序是什么?
答案 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为假的技巧(请注意这一点)