在某个时间点,我遇到了这个问题......并解决了它。但是,由于这是一个反复出现的问题,我现在已经忘记了解决方案,希望这个问题能够为我和其他人提供澄清:)
我正在创建一个基于几个问题的答案的变量。每个问题可以有三个值:1,2或NA。对于每次观察,1和2是相互排斥的。
我只是想创建一个变量,它是用" 1"编码的选项的复合。为每个人,并根据该代码给它一个值。
所以,让我说我有df
:
ID var1 var2 var3 var4
1 1 2 NA NA
2 NA NA 2 1
3 2 1 NA NA
4 2 NA 1 NA
然后我尝试根据以下语句重新编码:
df$var <-
ifelse(
as.numeric(df$var1) == 1,
"Gut instinct",
ifelse(
as.numeric(df$var2) == 1,
"Data",
ifelse(
as.numeric(df$var3) == 1,
"Science",
ifelse(
as.numeric(df$var4) == 1,
"Philosophy",
NA
)
)
)
)
但是,此代码仅基于&#34; ifelse&#34;的PARTIALLY代码。例如,df$var
可能会观察到肠道本能&#39;和哲学&#39;但是var2
和var3==1
的编码仍然是NA。
有关为何会发生这种情况的任何想法?
答案 0 :(得分:5)
比apply
更快的替代方案(使用@ MrFlick的数据):
vals <- c("Gut", "Data", "Science", "Phil")
intm <- dd[-1]==1 & !is.na(dd[-1])
dd$resp <- NA
dd$resp[row(intm)[intm]] <- vals[col(intm)[intm]]
快多少?在100万行:
#row/col assignment
user system elapsed
0.99 0.02 1.02
#apply
user system elapsed
11.98 0.04 12.30
在相同的数据集上尝试时给出相同的结果:
identical(flick$resp,latemail$resp)
#[1] TRUE
答案 1 :(得分:4)
这是一种没有嵌套ifelse语句的方法
#your data
dd<-data.frame(ID = 1:4,
var1 = c(1, NA, 2, 2),
var2 = c(2, NA, 1, NA),
var3 = c(NA, 2, NA, 2),
var4 = c(NA, 1, NA, NA)
)
resp <- c("Gut","Data","Sci","Phil")[apply(dd[,-1]==1,1,function(x) which(x)[1])]
cbind(dd, resp)
我使用apply
扫描行以查找第一行并使用该索引对响应值进行子集化。使用which
有助于处理NA
值。
答案 2 :(得分:3)
这是因为ifelse
(和==
)对NA
有特殊行为。具体来说,R不希望告诉您NA
与1
(或其他任何内容)不同,因为NA
通常用于表示可能}的值em>是任何东西,甚至可能是1
。
> 1 == NA
[1] NA
> ifelse(NA == 1, "yes", "no")
[1] NA
使用您的代码,如果NA
发生在1
之前(例如ID
2),则ifelse
语句将返回NA
,并且永远不会调用嵌套的FALSE
ifelse
。
答案 3 :(得分:1)
要回答您的问题,这取决于您的数据中的NAs。这应该排除你的问题
df <- data.frame( ID=1:4, var1= c(1, NA, 2, 2), var2= c(2, NA, 1, NA),
var3=c(NA,2,NA,2), var4=c(NA, 1, NA, NA))
df$var<-ifelse(as.numeric(df$var1)==1&!is.na(df$var1),"Gut instinct",
ifelse(as.numeric(df$var2)==1&!is.na(df$var2),"Data",
ifelse(as.numeric(df$var3)==1&!is.na(df$var3),"Science",
ifelse(as.numeric(df$var4)==1&!is.na(df$var4),"Philosophy",NA))))
但是,我会发现将数据重塑为“矩阵”更容易。而不是一张桌子,用矢量做。
data <- df
library(reshape2)
long <- melt(data, id.vars="ID")
long
这会给你一个矩阵。将var标题转换为更有意义的标题。
library(stringr)
long$variable <- str_replace(long$variable, "var1", "Gut Instinct")
long$variable <- str_replace(long$variable, "var2", "Data")
long$variable <- str_replace(long$variable, "var3", "Science")
long$variable <- str_replace(long$variable, "var4", "Philosophy")
现在,您可以根据每个结果决定做什么
long$var <- ifelse(long$value==1, long$variable, NA)
并将其转换回原始版本,如果您想要那样的话
reshape(data=long, timevar="ID",idvar=c("var", "variable"), v.names = "value", direction="wide")
HTH