【问题标题】:Appending a value from one table into another based on a criteria根据条件将一个表中的值附加到另一个表中
【发布时间】:2016-12-04 14:46:32
【问题描述】:

我有两个表,我正试图以特定方式加入。一个是提供 HEX 颜色及其关联的类别的简单 tibble:

library(tibble)
library(dplyr)

colors <- tibble(Category = c("A", "B", "C", "D"),
                  Colors = c("#0079c0", "#cc9900", "#252525", "#c5120e"))

# A tibble: 4 × 2
   Category Colours
     <chr>   <chr>
1        A #0079c0
2        B #cc9900
3        C #252525
4        D #c5120e

我有另一个 tibble 将类别列为行和列,并且以特定方式显示:

Main_Table <- tibble(Category = c("A", "B", "C", "D"),
                     A = c(NA, "A", NA, NA),
                     B = c(NA, NA, NA, NA),
                     C = c(NA, "C", NA, NA),
                     D = c("D", "D", NA, NA))

# A tibble: 4 × 5
  Category     A     B     C     D
     <chr> <chr> <lgl> <chr> <chr>
1        A  <NA>    NA  <NA>     D
2        B     A    NA     C     D
3        C  <NA>    NA  <NA>  <NA>
4        D  <NA>    NA  <NA>  <NA>

我想根据颜色对应的类别是否存在于以其名称命名的变量下,将颜色加入主表。例如,假设我想要包含 D 类的颜色,我最终会得到以下结果:

Main_Table_Goal <- tibble(Category = c("A", "B", "C", "D"),
                     A = c(NA, "A", NA, NA),
                     B = c(NA, NA, NA, NA),
                     C = c(NA, "C", NA, NA),
                     D = c("D", "D", NA, NA),
                     color = c("#c5120e", "#c5120e", NA, NA))

# A tibble: 4 × 6
    Category     A     B     C     D    color
      <chr>  <chr> <lgl>  <chr> <chr>   <chr>
1        A   <NA>    NA   <NA>     D  #c5120e
2        B      A    NA      C     D  #c5120e
3        C   <NA>    NA   <NA>  <NA>     <NA>
4        D   <NA>    NA   <NA>  <NA>     <NA>

如何使用dplyr 实现这一目标?我一直在尝试*_join 和其他技巧,但我没有得到任何结果。

编辑:我应该提到我希望最终将它包含在一个函数中,因此理想情况下代码可以灵活地容纳任意数量的类别。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    这是一个使用match的选项

    Main_Table %>% 
             mutate(color = colors$Colors[match(D, colors$Category)])
    # A tibble: 4 × 6
    #  Category     A     B     C     D   color
    #     <chr> <chr> <lgl> <chr> <chr>   <chr>
    #1        A  <NA>    NA  <NA>     D #c5120e
    #2        B     A    NA     C     D #c5120e
    #3        C  <NA>    NA  <NA>  <NA>    <NA>
    #4        D  <NA>    NA  <NA>  <NA>    <NA>
    

    【讨论】:

    • 我现在只是在玩match
    • match 函数正是让我无法理解的……谢谢!
    • 鉴于这个匹配思路,mutate_at(vars(A:D),funs(color = Colors[match(., Category)])) 是修改我的想法的方法,不是吗?
    • @akrun 谢谢。我刚刚更新了我的想法。到目前为止,我认为 funs 必须采用诸如 min、max、replace 等函数。color = Colors[match(., Category)]) 在我看来并不像一个函数。我猜 funs 包含您需要的任何操作,只要您的结果适合您使用的数据框。
    • @akrun 嘿,最近过得怎么样?从今年年初开始,我就跟不上SO了。这几天发生了什么?
    【解决方案2】:

    我不确定您的数据中有多少类别。但是,如果您只有四个(即 A、B、C 和 D),则以下是一种方法。我想使用一个数据框。所以我最初合并了两个数据框。因为我想使用mutate_at(),所以我将逻辑中的 B 转换为字符。然后,我用四种颜色替换了四个类别。最后,我删除了Colors 并将B 转换为逻辑。

    library(dplyr)
    
    left_join(Main_Table, colors) %>%
    mutate(B = as.character(B)) %>%
    mutate_at(vars(A:D),
              funs(color = recode(., A = Colors[1],
                                     B = Colors[2],
                                     C = Colors[3],
                                     D = Colors[4]))) %>%
    select(-Colors) %>%
    mutate(B = as.logical(B)) 
    

    鉴于 akrun 的想法,您可以执行以下操作。只要你能说出你有多少类别,你只需指定vars()中的列。如果所有列都是字符,则无需将逻辑转换为字符。

    left_join(Main_Table, colors) %>%
    mutate(B = as.character(B)) %>%
    mutate_at(vars(A:D),funs(color = Colors[match(., Category)])) %>%
    select(-Colors) %>%
    mutate(B = as.logical(B)) 
    
    
    #  Category     A     B     C     D A_color B_color C_color D_color
    #     <chr> <chr> <lgl> <chr> <chr>   <chr>   <chr>   <chr>   <chr>
    #1        A  <NA>    NA  <NA>     D    <NA>    <NA>    <NA> #c5120e
    #2        B     A    NA     C     D #0079c0    <NA> #252525 #c5120e
    #3        C  <NA>    NA  <NA>  <NA>    <NA>    <NA>    <NA>    <NA>
    #4        D  <NA>    NA  <NA>  <NA>    <NA>    <NA>    <NA>    <NA>
    

    【讨论】:

    • 谢谢。我应该提到这实际上是函数的一部分,最终我希望动态完成,因此类别的数量可能会有所不同。
    【解决方案3】:

    这是一个动态解决方案,您在顶部设置一次颜色参数:

    target_category <- 'D'  # set color
    target_category_table <- Main_Table %>%
        select_(target_category) %>%
        left_join(colors %>%
                      filter(Category == target_category) %>%
                      setNames(c(target_category, 'color')))
    goal_table <- Main_Table %>%
        bind_cols(select(target_category_table, color))
    goal_table
    

    结果:

    # A tibble: 4 × 6
      Category     A     B     C     D   color
         <chr> <chr> <lgl> <chr> <chr>   <chr>
    1        A  <NA>    NA  <NA>     D #c5120e
    2        B     A    NA     C     D #c5120e
    3        C  <NA>    NA  <NA>  <NA>    <NA>
    4        D  <NA>    NA  <NA>  <NA>    <NA>
    

    【讨论】:

    • 你可能刚刚救了我的培根。谢谢你,先生。 :)
    • @Phil 欢迎。将target_category_tablegoal_table 重新绑定在一起时要小心,因为它们在除此之外的情况下可能无法正确对齐。您可能应该在两个表中保留Category 变量并加入该变量,而不是使用bind_cols。如果您希望我相应地编辑解决方案,请告诉我。
    猜你喜欢
    • 2021-04-06
    • 2023-02-22
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 2021-12-27
    • 2020-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多