我的数据如下:
df <- read.table(tc <- textConnection("
var1 var2 var3 var4
1 1 7 NA
4 4 NA 6
2 NA 3 NA
4 4 4 4
1 3 1 1"), header = TRUE); close(tc)
我试图创建一个新列,如果匹配则返回1,否则返回0。
我的非工作代码如下所示:
df$var5 = ifelse("1" %in% df$var1,1,
ifelse("1" %in% df$var2,1,
ifelse("1" %in% df$var3,1,
ifelse("1" %in% df$var4,1,0))))
给我一张桌子:
var1 var2 var3 var4 var5
1 1 7 NA 1
4 4 NA 6 1
2 NA 3 NA 1
4 4 4 4 1
1 3 1 1 1
我真正想要的表应该看起来像
var1 var2 var3 var4 var5
1 1 7 NA 1
4 4 NA 6 0
2 NA 3 NA 0
4 4 4 4 0
1 3 1 1 1
我看过这些帖子:
https://jsfiddle.net/6ktgc4h9/5/
和
ifelse not working as expected in R
但我无法解决我的问题。
答案 0 :(得分:2)
正确的方法应该是
with(df, ifelse(var1 %in% 1,1,
ifelse(var2 %in% 1,1,
ifelse(var3 %in% 1,1,
ifelse(var4 %in% 1,1,0)))))
#[1] 1 0 0 0 1
原因是1 %in% df1$var1
只返回单个元素1。
1 %in% df$var1
#[1] TRUE
同样,在所有列中都有1,因此它将为所有ifelse
返回TRUE,从而产生值1.
而相反
df$var1 %in% 1
#[1] TRUE FALSE FALSE FALSE TRUE
返回与原始列具有相同length
的逻辑向量。实质上,通过使用%in%
,返回的长度将基于length
lhs
中对象的%in%
不需要ifelse
,更好的选择是,在逻辑矩阵(rowSum
)上使用df ==1
,并检查它是否不等于0,转换使用as.integer
二进制文件。
as.integer(rowSums(df == 1, na.rm =TRUE)!=0)
#[1] 1 0 0 0 1
或另一个选项Reduce
|
as.integer(Reduce(`|`, lapply(replace(df, is.na(df), 0), `==`, 1)))
#[1] 1 0 0 0 1
答案 1 :(得分:1)
如果整个行中存在1,则可以逐行检查,而不是分别对每列使用ifelse
,然后相应地返回1或0
as.numeric(apply(df, 1, function(x) any(x == 1)) %in% TRUE)
#[1] 1 0 0 0 1
只是为了更好地解释这些步骤:
apply(df, 1, function(x) any(x == 1))
#[1] TRUE NA NA FALSE TRUE
apply(df, 1, function(x) any(x == 1)) %in% TRUE
#[1] TRUE FALSE FALSE FALSE TRUE
as.numeric(apply(df, 1, function(x) any(x == 1)) %in% TRUE)
#[1] 1 0 0 0 1