Отформатируйте вложенные data.frame, сгруппированные по идентификаторам, используя tidyverse - PullRequest
1 голос
/ 01 августа 2020

У меня есть вложенное имя данных с двумя идентификаторами на строку, которое выглядит так:

df <- data.frame(
        sample = rep(paste0("s", 1:5), each = 5),
        ID1 = paste0("id1.", 1:5),
        ID2 = paste0("id2.", 1:5),
        counts = rep(1:5, each = 5)) %>%
    arrange(ID1) %>%
    group_by(ID1, ID2) %>% nest

Я хотел бы получить фрейм данных для дальнейшего анализа, в котором в первой строке указаны образцы, а в следующих столбцах указаны количества ( per ids) с объединенными идентификаторами в качестве имен столбцов:

df3 <- data.frame(
    sample = paste0("s", 1:5),
    "id1.1|id2.1" = 1:5,
    "id1.2|id2.2" = 1:5,
    "id1.3|id2.3" = 1:5,
    "id1.4|id2.4" = 1:5,
    "id1.5|id2.5" = 1:5)

Я уже начал формировать:

df2 <- df %>% 
    mutate(sample = data %>% map(pull, sample)) %>%
    mutate(counts = data %>% map(pull, counts))

Однако я не уверен, что было бы элегантным подходом для продолжения.

Ответы [ 2 ]

1 голос
/ 01 августа 2020

Мы можем создать столбец «ID», вставив «ID1», «ID2» и развернув в более широкий формат с помощью pivot_wider

library(dplyr)
library(purrr)
library(tidyr)
library(stringr)
df %>% 
     ungroup %>% 
     unnest %>% 
     transmute(ID = str_c(ID1, ID2, sep="_"), sample, counts) %>%
     pivot_wider(names_from = ID, values_from = counts)
# A tibble: 5 x 6
#  sample id1.1_id2.1 id1.2_id2.2 id1.3_id2.3 id1.4_id2.4 id1.5_id2.5
#  <chr>        <int>       <int>       <int>       <int>       <int>
#1 s1               1           1           1           1           1
#2 s2               2           2           2           2           2
#3 s3               3           3           3           3           3
#4 s4               4           4           4           4           4
#5 s5               5           5           5           5           5

Если есть несколько столбцов в «данных» и требуется подмножество некоторых столбцов

df %>%
   ungroup %>% 
   mutate(data = map(data, select, c(sample, counts))) %>%
   unnest %>% 
   transmute(ID = str_c(ID1, ID2, sep="_"), sample, counts) %>%
   pivot_wider(names_from = ID, values_from = counts)

Или в одной строке с dcast

dcast(setDT(unnest(df)), sample ~ paste(ID1, ID2, sep="_"), values.var = 'counts')
#    sample id1.1_id2.1 id1.2_id2.2 id1.3_id2.3 id1.4_id2.4 id1.5_id2.5
#1:     s1           1           1           1           1           1
#2:     s2           2           2           2           2           2
#3:     s3           3           3           3           3           3
#4:     s4           4           4           4           4           4
#5:     s5           5           5           5           5           5
1 голос
/ 01 августа 2020

Решение tidyr, которое разворачивает вложенный столбец и затем разворачивает его в широкий формат.

library(tidyr)

df %>%
  unite(ID, ID1, ID2) %>%
  unnest(data) %>%
  pivot_wider(names_from = ID, values_from = counts)

# # A tibble: 5 x 6
#   sample id1.1_id2.1 id1.2_id2.2 id1.3_id2.3 id1.4_id2.4 id1.5_id2.5
#   <chr>        <int>       <int>       <int>       <int>       <int>
# 1 s1               1           1           1           1           1
# 2 s2               2           2           2           2           2
# 3 s3               3           3           3           3           3
# 4 s4               4           4           4           4           4
# 5 s5               5           5           5           5           5

Или начиная с вашей работы

df %>% 
  ungroup() %>% 
  mutate(sample = data %>% map("sample"),
         counts = data %>% map("counts"), .keep = "unused") %>% 
  unite(ID, ID1, ID2) %>%
  unnest(-ID) %>%
  pivot_wider(names_from = ID, values_from = counts)

Обратите внимание, что mutate(sample = data %>% map("sample") - это ярлык mutate(sample = data %>% map(pull, sample)), который является функцией map().

...