【问题标题】:pivotting a list of data frames and merging them旋转数据框列表并合并它们
【发布时间】:2020-04-23 14:04:07
【问题描述】:

我有一个共享一些行和列的 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. 我不知道如何加入值和联合名称水果对。

任何帮助将不胜感激!

【问题讨论】:

  • 刚刚添加了预期的输出。所以我想将从 pivot_longer 获得的值作为列添加到所有名称+水果对的联合中

标签: r list pivot tidyverse


【解决方案1】:

如果我们遵循与 OP 尝试的方法类似的选项,即将list 中的每个数据集重新整形为“长”格式,然后使用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

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)

【讨论】:

  • 只是一个小问题!有没有办法将这些数据框数值强制转换为字符?我收到一条错误消息:Error: Column `C_BIG` can't be converted from character to numeric 在 pivot_longer 期间
  • @user171558 它是基于相同的示例还是不同的示例(因为我无法重现错误)
  • @user171558 你能试试bind_rows(all_data, .id = 'grp') %&gt;% type.convert(as.is = TRUE) %&gt;% pivot_longer(cols = c(-name, -grp), names_to = "fruit", values_to = "Value", values_drop_na = TRUE) %&gt;%pivot_wider(names_from = grp, values_from = Value)
  • 我对示例数据进行了修改!非常感谢您的帮助!
  • @user171558 你想让“AB”保持为“AB”还是NA,即你想要一个数字列还是一个字符
猜你喜欢
  • 2021-01-19
  • 2011-02-19
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-25
  • 2019-04-07
相关资源
最近更新 更多