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

如果另一个变量中的值在dplyr的列表中不匹配,则删除该变量中的值

  •  1
  • Bastien  · 技术社区  · 6 年前

    我有一个带有两个字段的表:

    dd <- data.frame(measure = c("a", "a", "b", "b", "c", "c"), class = c(1,11,2,22,3,33), stringsAsFactors = F)
    dd
      measure class
    1       a     1
    2       a    11
    3       b     2
    4       b    22
    5       c     3
    6       c    33
    

    对于每个 measure ,一个 class 是关联的。然而,并非所有 可以关联到每个 价值观。实际上,每个度量值只允许在 list :

    ls <- list(a=c(1,10), b=c(2,20,200), c=c(3,30,90))
    ls
    $`a`
    [1]  1 10
    
    $b
    [1]   2  20 200
    
    $c
    [1]  3 30 90
    

    good_match <- mapply(function(xx, yy) any(xx %in% yy), ls[dd$measure], dd$class)
    dd$measure[!good_match] <- NA
    dd
      measure class
    1       a     1
    2    <NA>    11
    3       b     2
    4    <NA>    22
    5       c     3
    6    <NA>    33
    

    不过,我想在 dplyr ,可能是 mutate ,这样我就可以

    library(dplyr)
    dd %>%  mutate(measure = ifelse(any(class %in% ls[[measure]]), measure, NA))
    Error in ls[[measure]] : recursive indexing failed at level 2
    

    我有一种感觉,它失败了,因为某种向量化的问题,但我卡住了。你知道实现我目标的另一种更优雅的方式吗?

    1 回复  |  直到 6 年前
        1
  •  2
  •   akrun    6 年前

    我们可以在转换命名的 list 到藏宝/数据框

    library(tidyverse)
    enframe(ls,  value = 'class') %>%
       unnest %>%
       right_join(dd, by = 'class') %>%
       transmute(measure = name, class)
    # A tibble: 6 x 2
    #  measure class
    #  <chr>   <dbl>
    #1 a           1
    #2 <NA>       11
    #3 b           2
    #4 <NA>       22
    #5 c           3
    #6 <NA>       33
    

    A base R 选项将使用 stack (而不是 enframe )以及 merge .

    注: ls 函数的名称。最好不要用函数名命名对象标识符

    推荐文章