将多个变量组合成R中的一个新变量

Combing multiple variables into a new variable in R

这对某些人来说可能非常简单,但我似乎无法让它在我的生活中发挥作用。我试过使用 cut 和 ifelse,但我得到的关卡没有我想要的值。任何想法将不胜感激。这是一些假数据:

 o5<-c(1,0,2,0,0,NA)
 o6<-c(NA,0,NA,2,0,NA)
 o7<-c(0,0,NA,2,2,1)
 ID<-seq(1,6,1)
 d1<-cbind(ID,o5,o6,o7)

     ID o5 o6 o7
[1,]  1  1 NA  0
[2,]  2  0  0  0
[3,]  3  2 NA NA
[4,]  4  0  2  2
[5,]  5  0  0  2
[6,]  6 NA NA  1

我正在尝试将 o5、o6、o7 组合成一个 o_all 变量,如下所示:

     ID o5 o6 o7 o_all
[1,]  1  1 NA  0  5
[2,]  2  0  0  0  0
[3,]  3  2 NA NA  5
[4,]  4  0  2  2  6
[5,]  5  0  0  2  7
[6,]  6 NA NA  1  7

每个o变量表示学生的年级水平。如果他们的那个等级有一个非零值,他们应该在 o_all 中得到等级水平的值(这是见证了特定行为开始的等级)。如果他们以两个或更多的等级表示,那么我 select 最早的值(ID #4 就是一个例子)。我也有很多丢失的数据需要考虑。谢谢!

这个呢?

res <- cbind(d1,o_all = as.numeric(gsub("[^0-9]", "", colnames(d1[,-1]))[apply(d1[,-1], 1, function(x) which((x!=0))[1])]))
res
     ID o5 o6 o7 o_all
[1,]  1  1 NA  0     5
[2,]  2  0  0  0    NA
[3,]  3  2 NA NA     5
[4,]  4  0  2  2     6
[5,]  5  0  0  2     7
[6,]  6 NA NA  1     7

然后您可以将 NA 替换为 0 例如通过 res[is.na(res[, 5]),5] <- 0

d1 <- cbind(d1, o_all = apply(d1[, -1], 1, function(x) {
  i <- which.max(!is.na(x) & x > 0) 
  if(x[i] == 0) 0 else i + 4
}))
#     ID o5 o6 o7 o_all
#[1,]  1  1 NA  0     5
#[2,]  2  0  0  0     0
#[3,]  3  2 NA NA     5
#[4,]  4  0  2  2     6
#[5,]  5  0  0  2     7
#[6,]  6 NA NA  1     7

您可以使用 apply 遍历每一行,选择具有最大值的列:

result <- apply(d1,1,function(row){which.max(row[2:length(row)])})

请注意,我使用 row[2:length(row)] 来排除 ID 列。 这会给你这样的结果:

> result
[1] 1 1 1 2 3 3

您可以使用它分配给您的 o_all 列:

o_all <- as.numeric(gsub("[^0-9]", "",colnames(d1)[result+1]))
cbind(d1,o_all)

这是一种完全矢量化的方法,随着数据集的增长,它可能比 apply 循环更快。可能的原因是我也将零转换为 NAs,因为它们的处理方式相同

is.na(d1) <- d1 == 0L
indx <- (rowSums(is.na(d1)) == (ncol(d1) - 1L)) + 1L
max.col(!is.na(d1[, -1L]), ties.method = "first") + c(4L, -1L)[indx]
## [1] 5 0 5 6 7 7