代码之家  ›  专栏  ›  技术社区  ›  aelhak

基于值的第一次出现生成变量

  •  0
  • aelhak  · 技术社区  · 6 年前

    我有5个重复的措施 pub1:pub5 每个取1到4的值。每个都是在不同的年龄测量的 age1:age5 是的。也就是说, pub1 是在 age1 …… pub5 age5 等。

    我想创建一个新变量 age_pb2 它显示了在 pub 是的。例如,对于单个x, 年龄2 意志平等 age3 如果第一次得分为2 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 回复  |  直到 6 年前
        1
  •  1
  •   Nic    6 年前
    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 在酒吧的柱子上 which(x == 2)[1] 每列的第一个匹配行,然后 which.min 要获取列索引号(分别为pub age),然后 paste 指定“年龄”(使用 eval(parse(text = variable name)) )相应的列。

    例如,在这里之后 应用 你得到

    [pub1 = 2,  pub2 = 1, pub3 = 2, pub4 = 4, pub5 = 2]
    

    这是每列第一次出现2个。最早的( 哪一分钟 )出现是为了第二个pub列,因此索引是 2 . 这贴上了“年龄”和eval分析变异。

    编辑

    对于所有年龄段的人来说,在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)]
    }
    

    不过,请注意 哪一分钟 取第一个最小值。例如,pub1和pub2在第一行都有一个1,因此上面的方法将age1指定给age1,而它也可以是age2。我不知道你想用这个做什么,所以不能说什么是更好的选择。