根据值的首次出现生成变量

时间:2018-07-13 13:47:48

标签: r function dplyr data-manipulation

我有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))]
})

1 个答案:

答案 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。我不知道您要怎么做,所以不能说什么是更好的选择。