我的数据框与下面的简化版相似:
MO1<-c("0","1","2","3")
MO2<-c("1","0","3","2")
MO3<-c("3","2","1","0")
df<-data.frame(MO1,MO2,MO3)
df
我正在尝试创建一个新变量,该变量将扫描观察所有1个值。然后,我希望这个新变量中的观察结果采用从中获取的列变量的名称,见下文:
MO1<-c("0","1","2","3")
MO2<-c("1","0","3","2")
MO3<-c("3","2","1","0")
MOTIVATION<-c("MO2","MO1","MO3","")
df2<-data.frame(MO1,MO2,MO3,MOTIVATION)
df2
抱歉,我不知道如何从上面显示结果数据框df2。
我的数据集中有989个观察值和19个不同的MO ..变量。
答案 0 :(得分:2)
另一个选择
> ind <- which(df==1, arr.ind = TRUE)
> df2 <- df # just cloning df
> df2$MOTIVATION <- NA
> df2$MOTIVATION[ind[,1]] <- names(df) [ind[,2]]
> df2
MO1 MO2 MO3 MOTIVATION
1 0 1 3 MO2
2 1 0 2 MO1
3 2 3 1 MO3
4 3 2 0 <NA>
答案 1 :(得分:1)
1)像这样试试max.col
。在每行前面插入1,然后找到最后一列的1。减去1,使其对应原始列号,缺少1给出0.然后用NA替换所有零,并查找相应的列名。
ix <- max.col(cbind(1, df) == 1, "last") - 1
transform(df, MOTIVATION = names(df)[replace(ix, ix == 0, NA)])
,并提供:
MO1 MO2 MO3 MOTIVATION
1 0 1 3 MO2
2 1 0 2 MO1
3 2 3 1 MO3
4 3 2 0 <NA>
2)以下是一种变体。我们计算max.col
,然后将每个结果乘以1,如果该行中有1,或者如果不是则为NA。
df1 <- df == 1
transform(df, MOTIVATION = names(df)[max.col(df1) * match(rowSums(df1), 1)])
答案 2 :(得分:1)
选项是将which
与df$MOTIVATION <- apply(df,1,function(x)names(df)[which(x==1)])
df
# MO1 MO2 MO3 MOTIVATION
# 1 0 1 3 MO2
# 2 1 0 2 MO1
# 3 2 3 1 MO3
# 4 3 2 0
结合使用:
cxfreeze
答案 3 :(得分:0)
以下是诀窍(请注意,这支持两列具有&#34; 1&#34的情况;不确定这是否是适合您的有效边缘情况。 (我稍微修改了原版的MO4,以便它包含两个&#34; 1&#34;
MO1<-c("0","1","2","3")
MO2<-c("1","2","3","2")
MO3<-c("3","2","1","0")
MO4<-c("3","2","1","1")
df<-data.frame(MO1,MO2,MO3,MO4)
df
findx <- function(dfx)
{
idx <- which(dfx=="1")
res <- lapply(idx, function(x) paste0('MO', x))
res
}
found <- apply(df,2,findx)
newdf <- unlist(found)
newdf
输出
&#34; MO2&#34; &#34; MO1&#34; &#34; MO3&#34; &#34; MO3&#34; &#34; MO4&#34;