我有5个称为pub1:pub5
的重复测量,每个测量的取值范围为1到4。每个测量都是在不同的年龄age1:age5
进行的。也就是说,pub1
的测量值为age1
。...pub5
的测量值为age5
等。
我想创建一个新变量age_pb2
,该变量显示在pub
中首次出现2的年龄。例如,对于单个x,如果第一次在age_pb2
中得分2,则age3
将等于pub3
我曾尝试修改以前的代码,但运气不佳。
library(tidyverse)
#Example data
N <- 2000
data <- data.frame(id = 1:2000,age1 = rnorm(N,6:8),age2 = rnorm(N,7:9),age3 = rnorm(N,8:10),
age4 = rnorm(N,9:11),age5 = rnorm(N,10:12),pub1 = rnorm(N,1:2),pub2 = rnorm(N,1:2),
pub3 = rnorm(N,1:2),pub4 = rnorm(N,1:2),pub5 = rnorm(N,1:2))
data <- data %>% mutate_at(vars(starts_with("pub")), funs(round(replace(., .< 0, NA), 0)))
#New variable showing first age at getting a score of 2 (doesn't work)
i1 <- grepl('^pub', names(data)) # index for pub columns
i2 <- grepl('^age', names(data)) # index for age columns
data[paste0("age_pb2")] <- lapply(2, function(i) {
j1 <- max.col(data[i1] == i, 'first')
j2 <- rowSums(data[i1] == i) == 0
data[i2][cbind(seq_len(nrow(data)), j1 *(NA^j2))]
})
答案 0 :(得分:1)
set.seed(1)
N <- 2000
data <- data.frame(id = 1:2000,age1 = rnorm(N,6:8),age2 = rnorm(N,7:9),age3 = rnorm(N,8:10),
age4 = rnorm(N,9:11),age5 = rnorm(N,10:12),pub1 = rnorm(N,1:2),pub2 = rnorm(N,1:2),
pub3 = rnorm(N,1:2),pub4 = rnorm(N,1:2),pub5 = rnorm(N,1:2)) %>%
mutate_at(vars(starts_with("pub")), funs(round(replace(., .< 0, NA), 0))) %>%
mutate(age_pb2 = eval(parse(text = paste0("age", which.min(apply(select(., starts_with("pub")), 2, function(x) which(x == 2)[1]))))))
工作方式,您apply
在pubs列上,并与which(x == 2)[1]
一起使用每列的第一个匹配行,然后使用which.min
获得列索引号(pub的年龄),然后您将paste
与“年龄”一起{使用eval(parse(text = variable name))
分配相应的列。
例如在apply
之后,您会得到
[pub1 = 2, pub2 = 1, pub3 = 2, pub4 = 4, pub5 = 2]
,这是每列首次出现2。最早(which.min
)出现在第二个pub列中,因此索引是2
。粘贴了“年龄”,并将其解析为变异。
编辑
在所有age_pbi的for循环中执行此操作可能更方便,或者在dplyr
中有一个我不知道的简单解决方案。
for (i in 1:5) {
index <- which.min(apply(select(data, starts_with("pub")), 2, function(x) which(x == i)[1]))
data[ ,paste0("age_pb", i)] <- data[ ,paste0("age", index)]
}
但是请注意,which.min
占据了最小值。例如。 pub1和pub2在第一行中都具有1,因此上述方法将age1分配给age_pb1,而也可能是age2。我不知道您要怎么做,所以不能说什么是更好的选择。