【问题标题】:Create a data frame from another containing a hierarchical taxonomy based on a column从另一个包含基于列的分层分类法创建数据框
【发布时间】:2020-03-16 17:42:31
【问题描述】:

我有一个表,其中包含一些类别的层次结构:

例如

“猫”属于“家畜”,“家畜”属于“动物”

下面我用 segment.parent 显示我的数据,它告诉每个实体所属的宏类别。我想创建一个新表,其中只有层次结构的叶子和它所属的两个宏类别的变量

segment.id     Name.                 segment.parent
   1            cat                       3
   2            dog                       3
   3            domestic animals          4
   4            animals                   NA
   5            cake                      7
   6            ice-cream                 7
   7            dessert                   8
   8            food                      NA
   9            main-course               8

我想要得到的是以下内容

segment.id     Name                 segment.parent   Name.parent              Name.parent.parent
   1            cat                       3           domestic animals          animals
   2            dog                       3           domestic animals          animals
   5            cake                      7           dessert                   food
   6            ice-cream                 7           dessert                   food

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    您必须做的第一件事是选择作为父母的细分。那些不是父母的将是叶子。

    parent.ids <- unique(df$segment.parent)
    

    现在使用 dplyr() 库,您可以只过滤那些 id 不是父 id 的实体,然后加入两次以获得父类别。

    library(dplyr)
    
    df %>%
      subset(! segment.id %in% parent.ids) %>%
      left_join(df, by = c("segment.parent" = "segment.id"), suffix = c("", ".x")) %>%
      left_join(df, by = c("segment.parent.x" = "segment.id"), suffix = c("", ".x")) %>%
      select(segment.id, Name., segment.parent, Name.parent = Name..x, Name.parent.parent = Name..x.x) %>%
      print(row.names = F)
    

    输出

     segment.id       Name. segment.parent      Name.parent Name.parent.parent
              1         cat              3 domestic animals            animals
              2         dog              3 domestic animals            animals
              5        cake              7          dessert               food
              6   ice-cream              7          dessert               food
              9 main-course              8             food               <NA>
    

    我冒昧地使用了left_join(),即使没有父类别,它也会检索行。这就是 main-course 出现在输出列表中的原因。如果只想带至少两级以上的物品,可以将left_join()替换为inner_join()

    【讨论】:

    • 您的解决方案有效,但是我不知道为什么每次使用 left_join 时它最终都会创建很多额外的行,因此我在每个 left_join 之后使用 na.omit(df) 添加了一个过滤器
    • 就像我说的,是因为left_join带来了上面没有两个分类的项目,可能只有一个。如果你想避免它,你可以使用 inner_join() 代替,所以你不需要过滤器。
    【解决方案2】:

    我不确定您正在使用的数据集有多大,但我的建议是拥有第二个数据集(即data2),其中包含相应的segment.parent 值以及其他两个变量。然后使用dplyr,您可以加入数据集并过滤重复项。

    library(dplyr)
    data3 <- inner_join(data1, data2, by = "segment.parent") %>%
      filter(duplicated(data3))
    
    > data3
      segment.id     Name. segment.parent      Name.parent Name.parent.parent
    1          1       cat              3 domestic animals            animals
    2          2       dog              3 domestic animals            animals
    3          5      cake              7           desert               food
    4          6 ice-cream              7           desert               food
    

    您的数据:

    data1 <- data.frame(segment.id = 1:9,
                        Name. = c("cat", "dog", "domestic animals", "animals", "cake", "ice-cream", "dessert", "food", "main-course"),
                        segment.parent = c(3, 3, 4, NA, 7, 7, 8, NA, 8))
    
    data2  <- data.frame(segment.parent = c(3, 3, 7, 7),
                         Name.parent = c("domestic animals", "domestic animals", "desert", "desert"),
                         Name.parent.parent = c("animals", "animals", "food", "food"))
    

    【讨论】:

      【解决方案3】:

      正如其他人所提到的,我不确定您的数据集有多大。以下解决方案是短期解决方案。您可能需要稍微重塑您的数据并查看pivoting

      library(dplyr)
      
      df <- data.frame(segment.id = seq(1, 9),
                       Name = c("cat", "dog",
                                 "domestic animals", "animals",
                                 "cake", "ice-cream",
                                 "dessert", "food",
                                 "main-course"),
      
                       segment.parent = c(3, 3, 4, NA,
                                          7, 7, 8, NA, 8),
                       stringsAsFactors = FALSE)
      
      
      df %>%
        dplyr::mutate(Name.parent = case_when(
          segment.parent == 3 ~ "domestic animals",
          segment.parent == 7 ~ "dessert",
        )) %>% 
        dplyr::mutate(Name.parent.parent = case_when(
            Name.parent == "domestic animals" ~ "animals",
            Name.parent == "dessert" ~ "food"
        )) %>% 
        na.omit()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-25
        • 1970-01-01
        • 1970-01-01
        • 2020-07-02
        • 2019-02-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多