Изменение формы фрейма данных со столбцом списка, созданным тидиграфом

Я работаю с пакетом tidygraph и пытаюсь найти «аккуратное» решение для приведенного ниже примера. Проблема на самом деле не связана с tidygraph и другими проблемами обработки данных, но я думаю, что это интересно людям, работающим с этим пакетом.

В следующем фрагменте кода я просто генерирую образцы данных.

library(tidyverse)
library(tidygraph)
library(igraph)
library(randomNames)
library(reshape2)

graph <- play_smallworld(1, 100, 3, 0.05) 

labeled_graph <- graph %>% 
                    activate(nodes) %>%
                    mutate(group = sample(letters[1:3], size = 100, replace = TRUE),
                           name = randomNames(100)
                           )

sub_graphs_df <- labeled_graph %>% 
                    morph(to_split, group) %>%
                    crystallise()

В результате data.frame выглядит следующим образом:

sub_graphs_df
# A tibble: 3 x 2
      name           graph
     <chr>          <list>
1 group: a <S3: tbl_graph>
2 group: b <S3: tbl_graph>
3 group: c <S3: tbl_graph>

Теперь о моей реальной проблеме. Я хочу применить функцию к каждому элементу столбца graph. Результат - просто именованный вектор.

sub_graphs_df$graph %>% map(degree)

Первое, что мне не нравится, это подмножество по $. Есть ли способ лучше?

Затем я хочу преобразовать этот результат в один data.frame с 3 столбцами. Один столбец для name (атрибут имени векторов), один для group (атрибут имени списка) и один для number (элементы векторов).

Пробовал melt из пакета reshape2.

sub_graphs_df$graph %>% map(degree) %>% melt

Он работает прилично, но имена утеряны, и, когда я его читал, вместо него следует использовать tidyr. Однако мне не удалось заставить gather работать, потому что принимаются только data.frames.

Другой вариант - unlist:

sub_graphs_df$graph %>% map(degree) %>% unlist

Здесь группа и имя находятся в атрибуте names, и мне пришлось бы восстанавливать их с помощью регулярных выражений.

Я почти уверен, что есть простой способ, о котором я просто не мог придумать.


person Alex    schedule 11.01.2018    source источник
comment
Другой вариант - sub_graphs_df %>% mutate(newout = map(graph, ~degree(.x) %>% stack)) %>% .$newout %>% setNames(., sub_graphs_df$name) %>% bind_rows(., .id = 'name')   -  person akrun    schedule 11.01.2018


Ответы (1)


Мы можем создать столбец list с mutate, применяя функцию с map, извлечь names и целое число и unnest, чтобы создать набор данных "длинного" формата

sub_graphs_df %>%
   mutate(newout = map(graph, degree)) %>%
   transmute(name, group = map(newout, ~.x %>% names), number = map(newout, as.integer)) %>%
    unnest
# A tibble: 100 x 3
#   name     group              number
#   <chr>    <chr>               <int>
# 1 group: a Seng, Trevor            0
# 2 group: a Buccieri, Joshua        1
# 3 group: a Street, Aimee           2
# 4 group: a Gonzalez, Corey         2
# 5 group: a Barber, Monique         1
# 6 group: a Doan, Christina         1
# 7 group: a Ninomiya, Janna         1
# 8 group: a Bazemore, Chao          1
# 9 group: a Perfecto, Jennifer      1
#10 group: a Lopez Jr, Vinette       0
# ... with 90 more rows
person akrun    schedule 11.01.2018
comment
Из какого пакета происходит сокращение ~.x? - person Alex; 11.01.2018
comment
@Alex map от purrr, а также связанный анонимный звонок - person akrun; 11.01.2018