将多个变量组合成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
循环更快。可能的原因是我也将零转换为 NA
s,因为它们的处理方式相同
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
这对某些人来说可能非常简单,但我似乎无法让它在我的生活中发挥作用。我试过使用 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
循环更快。可能的原因是我也将零转换为 NA
s,因为它们的处理方式相同
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