Создайте фрейм данных из другого, содержащего иерархическую таксономию на основе столбца - PullRequest
1 голос
/ 16 марта 2020

У меня есть таблица, содержащая иерархическую структуру некоторых категорий:

например

"кошка" относится к "домести c животных" и "домести c животных" принадлежат «животным»

ниже. Я показываю свои данные с помощью plot.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

Ответы [ 3 ]

1 голос
/ 16 марта 2020

Первое, что вам нужно, это выбрать сегменты, которые являются родителями. Те, кто не являются родителями, будут оставлены.

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

Теперь, используя библиотеку dplyr (), вы можете отфильтровать только те сущности, чьи идентификаторы не являются родительскими, а затем объединиться два раза, чтобы получить категории отца.

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(), который будет извлекать строки, даже если нет категории отца. Вот почему основной курс появляется в списке вывода. Если вы хотите взять с собой только те предметы, которые имеют как минимум два уровня выше, вы можете заменить left_join() на inner_join().

0 голосов
/ 16 марта 2020

Как уже упоминали другие, я не уверен, насколько велик ваш набор данных. Приведенное ниже решение является краткосрочным решением. Возможно, вам придется слегка изменить ваши данные и посмотреть на 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()
0 голосов
/ 16 марта 2020

Я не уверен, насколько велик набор данных, с которым вы работаете, но я бы предложил иметь второй набор данных (т.е. 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"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...