R 中的嵌套 ifelse() 语句未产生所需的结果
Nested ifelse() statement in R not producing the desired results
我有一个布尔变量数据集,我正在尝试使用 ifelse() 基于 3 个现有布尔值生成一个新变量。
我想执行的规则是:
- 如果三列中的任何一列的值为 1, 1
- 如果三列的值都为 0, 0
- 如果三列的值都为 NA,则 NA
- 如果三列有0和NA的某种组合,0
下面是生成样本的代码,其中包含 3 个变量,我想用它来创建第四个变量:
df <- structure(list(var1 = c(NA, NA, NA, 0,1),
var2 = c(1, NA, 0,0, 1),
var3 = c(NA, NA, NA,0,1)), class = "data.frame", row.names = c(NA, -5L))
我尝试了以下方法来根据我想要的规则生成新变量:
df$newvar1 <-ifelse(df$var1 == 1 | df$var2 == 1 |df$var3 == 1, 1,
ifelse((is.na(df$var1) & is.na(df$var2) & is.na(df$var3)), NA,0))
df$newvar2 <- ifelse((is.na(df$var1)|df$var1==0) &
(is.na(df$var2)|df$var2==0) &
(is.na(df$var3)|df$var3==0),0,
ifelse(df$var1 == 1 | df$var2 == 1 |df$var3 == 1, 1,
ifelse(is.na(df$var1) & is.na(df$var2) & is.na(df$var3), NA,NA)))
df$newvar3 <-ifelse(df$var1 == 1 | df$var2 == 1 |df$var3 == 1, 1,
ifelse((is.na(df$var1) & is.na(df$var2) & is.na(df$var3)), NA,
ifelse((is.na(df$var1)|df$var1==0) &
(is.na(df$var2)|df$var2==0) &
(is.na(df$var3)|df$var3==0),0,0)))
我不明白为什么 newvar1 和 newvar3 的 NA 值对应于 NA 和 0 的组合,而这两个示例都在 na 规范之间使用“&”(结果中的第 3 行)。
我假设 NA 不会出现在 newvar2 中,因为第一个 ifelse() 函数具有先例。
对 ifelse() 函数的任何见解或关于如何获得我正在寻找的结果的建议都将非常有帮助。
这给出了您的预期结果:
df$newvar <- 0
df$newvar[Reduce(`|`, lapply(df[1:3], `%in%`, 1))] <- 1
df$newvar[Reduce(`&`, lapply(df[1:3], is.na))] <- NA
df
# var1 var2 var3 newvar
# 1 NA 1 NA 1
# 2 NA NA NA NA
# 3 NA 0 NA 0
# 4 0 0 0 0
# 5 1 1 1 1
这默认为 0 并且仅在已知条件下更改值,这意味着如果有任何行带有 NA
和 1
(有或没有 0
),它将被分配 0
。对此进行测试并不难,但这不符合您的逻辑。
这是使用 rowSums
的另一种可能的选择:
df$newvar <- +(rowSums(df, na.rm = TRUE) * NA ^ (rowSums(!is.na(df)) == 0) > 0)
# var1 var2 var3 newvar
#1 NA 1 NA 1
#2 NA NA NA NA
#3 NA 0 NA 0
#4 0 0 0 0
#5 1 1 1 1
我有一个布尔变量数据集,我正在尝试使用 ifelse() 基于 3 个现有布尔值生成一个新变量。
我想执行的规则是:
- 如果三列中的任何一列的值为 1, 1
- 如果三列的值都为 0, 0
- 如果三列的值都为 NA,则 NA
- 如果三列有0和NA的某种组合,0
下面是生成样本的代码,其中包含 3 个变量,我想用它来创建第四个变量:
df <- structure(list(var1 = c(NA, NA, NA, 0,1),
var2 = c(1, NA, 0,0, 1),
var3 = c(NA, NA, NA,0,1)), class = "data.frame", row.names = c(NA, -5L))
我尝试了以下方法来根据我想要的规则生成新变量:
df$newvar1 <-ifelse(df$var1 == 1 | df$var2 == 1 |df$var3 == 1, 1,
ifelse((is.na(df$var1) & is.na(df$var2) & is.na(df$var3)), NA,0))
df$newvar2 <- ifelse((is.na(df$var1)|df$var1==0) &
(is.na(df$var2)|df$var2==0) &
(is.na(df$var3)|df$var3==0),0,
ifelse(df$var1 == 1 | df$var2 == 1 |df$var3 == 1, 1,
ifelse(is.na(df$var1) & is.na(df$var2) & is.na(df$var3), NA,NA)))
df$newvar3 <-ifelse(df$var1 == 1 | df$var2 == 1 |df$var3 == 1, 1,
ifelse((is.na(df$var1) & is.na(df$var2) & is.na(df$var3)), NA,
ifelse((is.na(df$var1)|df$var1==0) &
(is.na(df$var2)|df$var2==0) &
(is.na(df$var3)|df$var3==0),0,0)))
我不明白为什么 newvar1 和 newvar3 的 NA 值对应于 NA 和 0 的组合,而这两个示例都在 na 规范之间使用“&”(结果中的第 3 行)。
我假设 NA 不会出现在 newvar2 中,因为第一个 ifelse() 函数具有先例。
对 ifelse() 函数的任何见解或关于如何获得我正在寻找的结果的建议都将非常有帮助。
这给出了您的预期结果:
df$newvar <- 0
df$newvar[Reduce(`|`, lapply(df[1:3], `%in%`, 1))] <- 1
df$newvar[Reduce(`&`, lapply(df[1:3], is.na))] <- NA
df
# var1 var2 var3 newvar
# 1 NA 1 NA 1
# 2 NA NA NA NA
# 3 NA 0 NA 0
# 4 0 0 0 0
# 5 1 1 1 1
这默认为 0 并且仅在已知条件下更改值,这意味着如果有任何行带有 NA
和 1
(有或没有 0
),它将被分配 0
。对此进行测试并不难,但这不符合您的逻辑。
这是使用 rowSums
的另一种可能的选择:
df$newvar <- +(rowSums(df, na.rm = TRUE) * NA ^ (rowSums(!is.na(df)) == 0) > 0)
# var1 var2 var3 newvar
#1 NA 1 NA 1
#2 NA NA NA NA
#3 NA 0 NA 0
#4 0 0 0 0
#5 1 1 1 1