【问题标题】:Create a new column which looks-up values in other columns创建一个在其他列中查找值的新列
【发布时间】:2019-04-24 05:41:23
【问题描述】:

我有以下数据:

df <- data.frame(a=c(0,0,0,1,1,1),
                 b=c(1,2,3,1,2,3), 
                 c=c("a","b","c","x","y","z"),
                 stringsAsFactors = FALSE) 

df

#>   a b c
#> 1 0 1 a
#> 2 0 2 b
#> 3 0 3 c
#> 4 1 1 x
#> 5 1 2 y
#> 6 1 3 z

我想创建第 4 列“d”,它从“c”返回值,其中“a”= 0 且 b=b,如下所示:

#>   a b c d
#> 1 0 1 a a
#> 2 0 2 b b
#> 3 0 3 c c
#> 4 1 1 x a
#> 5 1 2 y b
#> 6 1 3 z c

我试过了:

df %>% mutate(d = c[a==0 & b==b])

但这不起作用。

如何使用 dplyr 创建列“d”?

【问题讨论】:

  • b == b 是错字吗?
  • b = b 将始终为 TRUE,因此如果是这种情况,您可以取消该条件。您也说过b = b &amp; a = 0,但在您的示例中,您仍然为d 列提供值,其中a != 0。你能进一步解释一下吗?
  • 所以对于第 4 行,我想从 a==0 和 b==1 ("a") 的 "c" 返回值。对于第 5 行,我想从“c”返回值,其中 a==0 和 b==2(“b”)。对于第 6 行,我想从 a==0 和 b==3 ("c") 的 "c" 返回值。

标签: r dplyr


【解决方案1】:

dplyr 解决方案:

df1 <-  df[df$a == 0,-1]
inner_join(df, df1, by = "b")

#   a b c.x c.y
# 1 0 1   a   a
# 2 0 2   b   b
# 3 0 3   c   c
# 4 1 1   x   a
# 5 1 2   y   b
# 6 1 3   z   c

【讨论】:

  • 这是merge(df, df[df$a == 0, c("b","c")], by="b") 或重命名merge(df, transform(df[df$a==0,], d=c)[c("b","d")], by="b") 的基本R 变体
【解决方案2】:

使用基础 R,您可以执行以下操作。

inx <- match(df$b, df$b[df$a == 0])
df$d <- df$c[inx]

df
#  a b c d
#1 0 1 a a
#2 0 2 b b
#3 0 3 c c
#4 1 1 x a
#5 1 2 y b
#6 1 3 z c

【讨论】:

    【解决方案3】:

    任何tidyverse 的可能性可能是:

    df %>%
     mutate(d = ifelse(a == 0, c, NA_character_)) %>%
     group_by(b) %>%
     fill(d)
    
          a     b c     d    
      <dbl> <dbl> <chr> <chr>
    1     0     1 a     a    
    2     1     1 x     a    
    3     0     2 b     b    
    4     1     2 y     b    
    5     0     3 c     c    
    6     1     3 z     c  
    

    你也可以安排:

    df %>%
     mutate(d = ifelse(a == 0, c, NA_character_)) %>%
     group_by(b) %>%
     fill(d) %>%
     arrange(a, b, c)
    
          a     b c     d    
      <dbl> <dbl> <chr> <chr>
    1     0     1 a     a    
    2     0     2 b     b    
    3     0     3 c     c    
    4     1     1 x     a    
    5     1     2 y     b    
    6     1     3 z     c 
    

    为了应对@divibisan 提到的场景,您可以这样做:

    df %>%
     mutate(d = ifelse(a == 0, c, NA_character_)) %>%
     group_by(b) %>%
     fill(d, .direction = "up") %>%
     fill(d, .direction = "down") %>%
     arrange(a, b, c)
    

    【讨论】:

    • 聪明的解决方案!一个问题是,要使fill 正常运行,非NA 行(a ==0)必须排在第一位(尝试在df2 &lt;- df[6:1,] 上执行此操作)。
    • 谢谢 - 但由于某种原因,列 d 输出是数字,其中 a=1、b=2 和 c=3。有什么想法吗?
    • @Rez99 因为列c 实际上是一个因素,而不是一个字符。你可以用as.character修复它,或者在制作数据框时使用stringsAsFactor=F参数
    • @divibisan 更新了帖子,感谢您的关注 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多