поворот списка фреймов данных и их объединение - PullRequest
2 голосов
/ 06 января 2020

У меня есть список из 3 фреймов данных, которые разделяют некоторые строки и столбцы

ДАННЫЕ

all_data <- list(questionnaireA = structure(list(name = structure(2:1, .Label = c("James", 
          "Shawn"), class = "factor"), banana = c(1, 0), grapes = c(1, 
          1), orange = c("AB", 1)), class = "data.frame", row.names = c(NA, 
          -2L)), questionnaireB = structure(list(name = structure(2:1, .Label = c("Chris", 
          "James"), class = "factor"), orange = c(1, 0), banana = c(1, 
          0)), class = "data.frame", row.names = c(NA, -2L)), questionnaireC = structure(list(
          name = structure(3:1, .Label = c("Donald", "James", "Shawn"
          ), class = "factor"), banana = c(1, 0, 0), raisins = c(1, 
          1, 1), grapes = c(1, 1, 0), cake = c(0, 1, 0)), class = "data.frame", row.names = c(NA, -3L)))
$questionnaireA
   name banana grapes orange
1 Shawn      1      1     AB
2 James      0      1      1

$questionnaireB
   name orange banana
1 James      1      1
2 Chris      0      0

$questionnaireC
    name banana raisins grapes cake
1  Shawn      1       1      1    0
2  James      0       1      1    1
3 Donald      0       1      0    0
library(tidyverse)
map(all_data, ~ .x %>%
    pivot_longer(cols=-name, names_to="fruit"))
  1. Не уверен, как переименовать значение в имя фрейма данных.
  2. Я не знаю, как соединить значения и объединить пару имен фруктов.

Любая помощь будет оценена!

1 Ответ

2 голосов
/ 06 января 2020

Если мы следуем тому же параметру, что и в методе попытки OP, то есть изменим формат на «long» каждого набора данных в list, затем l oop с imap, создайте имя list1 элемент в качестве нового столбца, используйте pivot_longer для преобразования в «длинный» формат, затем создайте столбец последовательности по группам и измените в «широкий» формат с помощью pivot_wider

library(dplyr)
library(tidyr)
library(purrr)
imap_dfr(all_data, ~
                   .x %>% 
                      mutate(grp = .y) %>%
                      pivot_longer(cols = -c(name, grp), 
                         names_to = "fruit", values_to = "Value")) %>% 
   #group_by(name, grp, fruit) %>% 
   #mutate(rn = row_number()) %>%
   pivot_wider(names_from = grp, values_from = Value)

Или сделайте это более эффективно, привязав все наборы данных к одним данным с помощью bind_cols, выполните pivot_longer, удаляя отсутствующие значения с помощью value_drop_na = TRUE, а затем сделайте то же самое, что и в приведенном выше решении

bind_rows(all_data, .id = 'grp') %>%
    pivot_longer(cols = c(-name, -grp), names_to = "fruit", 
         values_to = "Value", values_drop_na = TRUE) %>%
    # sequence column creation is not really required for the example
    # as there are no duplicates
    #group_by(name, grp, fruit) %>% 
    #mutate(rn = row_number()) %>%
    pivot_wider(names_from = grp, values_from = Value)

Обновление

На основании новых данных с некоторым смешением в типах столбцов, если нам нужно, чтобы значения, такие как "AB", оставались такими же, их необходимо преобразовать в character class

imap_dfr(all_data, ~
               .x %>% 
                  mutate_at(-1, as.character) %>% 
                  mutate(grp = .y) %>% 
                  pivot_longer(cols = -c(name, grp), names_to = "fruit",
                    values_to = "Value")) %>% 
       pivot_wider(names_from = grp, values_from = Value)

Или эффективный подход, аналогичный bind_rows ранее (но здесь это невозможно сделать из-за разных типов столбцов)

map_dfr(all_data, ~
         .x %>%
            mutate_at(-1, as.character), .id = 'grp') %>%  
    pivot_longer(cols = c(-name, -grp), names_to = "fruit", 
          values_to = "Value", values_drop_na = TRUE)  %>%
    pivot_wider(names_from = grp, values_from = Value)
...