使用矩阵值有条件地替换data.frame列。 R中的VLOOKUP

时间:2014-09-13 14:53:25

标签: r matrix dataframe vlookup

我在R中有一个非常简单的疑问,但我仍然无法在以前的答案中找到我需要的解决方案,或者我错过了它。我想要一种vlookup(如Excel)公式,但仅适用于数据框中的特定行。假设我有一个如下数据框:

    id obs year   a1    a2        b1     b2         c
   604  43 2003   NA    NA        NA     NA        NA
   605  43 2004   NA    NA        NA     NA        NA
   606  43 2005 9000  6421   1748365 0.1616  36872152
   769  55 2003   NA    NA        NA     NA        NA
   770  55 2004   NA    NA        NA     NA        NA
   771  55 2005 2500 12449        NA     NA 125992307
   844  61 2003 1800 11633 157977428 0.0089  69901689
   845  61 2004 2200 14841 228966763 0.0012  86853166
   846  61 2005 2500 15559 345889717 0.0081 103029905
  2209 178 2003   NA    NA        NA     NA        NA
  2210 178 2004  200 45093        NA     NA  11668685
  2211 178 2005  250 47202    610500 0.1605  12813908

然后,我将一个公式应用于数据中的所有完整案例,因此,对于这个特定的例子,我将得到一个矩阵,其中包含5行结果(每次观察2个结果),我在这里显示:

   id    x  y
  606 8000 30
  844 1700 90
  845 8000 61
  846  400 82
 2211  600 30

所以现在,我基本上想要的是,仅对于数据框中2005年的行,检查矩阵中匹配(通过id)的位置并修改数据框中的特定列(我之前创建的“值“)及其对应的结果在矩阵的”y“列中。在这里考虑一些要点:(a)对于非完整案例,它应提供NA,(b)我只希望修改2005年;其他年份将随后使用其他后续公式进行修改,这些公式将提供不同的矩阵结果。鉴于此,据我所知,mergematchcbindplyr等函数会影响整个列,我不是在寻找它。其他选项如%in%%l%也不起作用,或者我错误地使用它们。这是我到目前为止所尝试的并没有成功:

df$value [c(df$year==2005)]  <-  matrix[,3[matrix[,1]==df$id]]

df$value [c(df$year==2005)]  <-  matrix[,3][matrix[,1]==df$id]

也许循环可以成为解决方案,但我仍然在学习如何构建它们并且也是无用的。 这是我期望的结果,以便更好地理解。

    id obs year   a1    a2        b1     b2         c value  
   604  43 2003   NA    NA        NA     NA        NA    NA
   605  43 2004   NA    NA        NA     NA        NA    NA
   606  43 2005 9000  6421   1748365 0.1616  36872152    30
   769  55 2003   NA    NA        NA     NA        NA    NA
   770  55 2004   NA    NA        NA     NA        NA    NA
   771  55 2005 2500 12449        NA     NA 125992307    NA
   844  61 2003 1800 11633 157977428 0.0089  69901689    NA
   845  61 2004 2200 14841 228966763 0.0012  86853166    NA
   846  61 2005 2500 15559 345889717 0.0081 103029905    82
  2209 178 2003   NA    NA        NA     NA        NA    NA
  2210 178 2004  200 45093        NA     NA  11668685    NA
  2211 178 2005  250 47202    610500 0.1605  12813908    30

非常感谢任何提示并继续做好工作。我已经检查了这个网络大约一年了,它给了我很多帮助!!!

3 个答案:

答案 0 :(得分:2)

使用akrun的数据,你也可以使用:

ifelse(df1$year == 2005 & rowSums(sapply(df1[-(1:3)], is.na)) == 0, 
       m1[match(df1$id, m1[, "id"]), "y"], 
       NA)
 #[1] NA NA 30 NA NA NA NA NA 82 NA NA 30

即。如果年份是2005年并且行中没有NA,请从矩阵中取相应的“y”NA

答案 1 :(得分:1)

您可以尝试:df1data.framem1矩阵

  indx <- which(df1$year==2005)

更新

我想我错过了其中一个条件,即complete.cases(尽管在示例数据集中,它没有改变结果)。新indx应为

  indx <- which(df1$year==2005 & !rowSums(is.na(df1[-(1:3)]))) #inspired from @alexis_laz answer

  df1$value <- NA
  df1$value[indx[df1$id[indx] %in% m1[,"id"] ]] <- m1[, "y"][m1[,"id"] %in% df1$id[indx]]
   df1
  #     id obs year   a1    a2        b1     b2         c value
  #1   604  43 2003   NA    NA        NA     NA        NA    NA
  #2   605  43 2004   NA    NA        NA     NA        NA    NA
  #3   606  43 2005 9000  6421   1748365 0.1616  36872152    30
  #4   769  55 2003   NA    NA        NA     NA        NA    NA
  #5   770  55 2004   NA    NA        NA     NA        NA    NA
  #6   771  55 2005 2500 12449        NA     NA 125992307    NA
  #7   844  61 2003 1800 11633 157977428 0.0089  69901689    NA
  #8   845  61 2004 2200 14841 228966763 0.0012  86853166    NA
  #9   846  61 2005 2500 15559 345889717 0.0081 103029905    82
  #10 2209 178 2003   NA    NA        NA     NA        NA    NA
  #11 2210 178 2004  200 45093        NA     NA  11668685    NA
  #12 2211 178 2005  250 47202    610500 0.1605  12813908    30

数据

 df1 <-   structure(list(id = c(604L, 605L, 606L, 769L, 770L, 771L, 844L, 
 845L, 846L, 2209L, 2210L, 2211L), obs = c(43L, 43L, 43L, 55L, 
 55L, 55L, 61L, 61L, 61L, 178L, 178L, 178L), year = c(2003L, 2004L, 
 2005L, 2003L, 2004L, 2005L, 2003L, 2004L, 2005L, 2003L, 2004L, 
 2005L), a1 = c(NA, NA, 9000L, NA, NA, 2500L, 1800L, 2200L, 2500L, 
 NA, 200L, 250L), a2 = c(NA, NA, 6421L, NA, NA, 12449L, 11633L, 
 14841L, 15559L, NA, 45093L, 47202L), b1 = c(NA, NA, 1748365L, 
 NA, NA, NA, 157977428L, 228966763L, 345889717L, NA, NA, 610500L
 ), b2 = c(NA, NA, 0.1616, NA, NA, NA, 0.0089, 0.0012, 0.0081, 
 NA, NA, 0.1605), c = c(NA, NA, 36872152L, NA, NA, 125992307L, 
 69901689L, 86853166L, 103029905L, NA, 11668685L, 12813908L)), .Names = c("id", 
 "obs", "year", "a1", "a2", "b1", "b2", "c"), class = "data.frame", row.names = c(NA, 
 -12L))

 m1 <- structure(c(606L, 844L, 845L, 846L, 2211L, 8000L, 1700L, 8000L, 
 400L, 600L, 30L, 90L, 61L, 82L, 30L), .Dim = c(5L, 3L), .Dimnames = list(
 NULL, c("id", "x", "y")))

答案 2 :(得分:0)

如果我在你的鞋子里,我可能会编写一个for循环和一个循环遍历每条记录的函数,因为看起来他们根据条件会有几个不同的逻辑。

以下是我对您的“规范”的理解:

  1. 仅处理符合某些条件的行(在这种情况下,年份等于2005年),而不是affecting the whole column
  2. 这是一些代码,它有点长,但我不知道是否将数据框分成两部分,然后使用melt / cast将它们重新组合在一起的想法将有所帮助:

    mytext1 <- "id obs year   a1    a2        b1     b2         c
    604  43 2003   NA    NA        NA     NA        NA
    605  43 2004   NA    NA        NA     NA        NA
    606  43 2005 9000  6421   1748365 0.1616  36872152
    769  55 2003   NA    NA        NA     NA        NA
    770  55 2004   NA    NA        NA     NA        NA
    771  55 2005 2500 12449        NA     NA 125992307
    844  61 2003 1800 11633 157977428 0.0089  69901689
    845  61 2004 2200 14841 228966763 0.0012  86853166
    846  61 2005 2500 15559 345889717 0.0081 103029905
    2209 178 2003   NA    NA        NA     NA        NA
    2210 178 2004  200 45093        NA     NA  11668685
    2211 178 2005  250 47202    610500 0.1605  12813908"
    
    mytext2 <- "id    x  y
    606 8000 30
    844 1700 90
    845 8000 61
    846  400 82
    2211  600 30"
    
    data.1 <- read.table(text=mytext1, header=TRUE)
    data.2 <- read.table(text=mytext2, header=TRUE)
    require(plyr)
    require(reshape2)
    a <- merge(x=subset(data.1, year==2005), y=data.2, by="id")
    b <- subset(data.1, year!=2005)
    a.new <- melt(a, id.vars=c('id'))
    b.new <- melt(b, id.vars=c('id'))
    result.new <- rbind(a.new, b.new)
    result <- dcast(result.new, id ~ variable)
    

    现在您的结果如下:

    > result
    id obs year   a1    a2        b1     b2         c    x  y
    1   604  43 2003   NA    NA        NA     NA        NA   NA NA
    2   605  43 2004   NA    NA        NA     NA        NA   NA NA
    3   606  43 2005 9000  6421   1748365 0.1616  36872152 8000 30
    4   769  55 2003   NA    NA        NA     NA        NA   NA NA
    5   770  55 2004   NA    NA        NA     NA        NA   NA NA
    6   844  61 2003 1800 11633 157977428 0.0089  69901689   NA NA
    7   845  61 2004 2200 14841 228966763 0.0012  86853166   NA NA
    8   846  61 2005 2500 15559 345889717 0.0081 103029905  400 82
    9  2209 178 2003   NA    NA        NA     NA        NA   NA NA
    10 2210 178 2004  200 45093        NA     NA  11668685   NA NA
    11 2211 178 2005  250 47202    610500 0.1605  12813908  600 30
    

    你仍然需要在最后或在将它们重新组合之前更改名称..:)