将数据按另一列分隔成多列(使用tidyr)

5

我正在整理数据,其中所需的列名映射在单独的列中给出,如下所示:

df <- data.frame(splitme = c("6, 7, 8, 9", "1,2,3"), 
                 type = c("A, B, C, D", "A, C, D"))

df的样子如下:

     splitme       type
 6, 7, 8, 9       A, B, C, D
      1,2,3       A, C, D

期望的输出应该如下所示:
desired_output <- data.frame(A = c(6,1), 
                             B = c(7, NA), 
                             C = c(8,2), 
                             D = c(9,3))

i.e.:

  A  B C D
  6  7 8 9
  1 NA 2 3

如果没有一些行缺少类型,使用 tidyr::separate 将会是一个非常简单的任务。
## Not correctly aligned
df %>% 
tidyr::separate(splitme, into = c("A", "B", "C", "D")) %>% 
select(-type)

但很明显,对齐存在问题。如果into参数可以接受指定分割规则的列,那就好了。也许可以使用基于purr::pmap_df的策略来解决这个问题?

2个回答

5
您可以使用separate_rows然后使用spread进行重塑:
library(dplyr); library(tidyr);
df %>% 
    # add a row identification number for reshaping purpose
    mutate(rn = row_number()) %>% 
    separate_rows(splitme, type) %>% 
    spread(type, splitme) %>% 
    select(-rn)

#  A    B C D
#1 6    7 8 9
#2 1 <NA> 2 3

1
使用purrr:map2_dfr,而不是解析splitme列,我们直接在data.frame调用中使用字符串。我们命名列,map2_dfr绑定行并处理缺失值。
library(purrr)
map2_dfr(df$splitme,df$type,
         ~setNames(eval(parse(text=paste0("data.frame(",.x,")"))),
                   strsplit(.y,", ")[[1]]))
#   A  B C D
# 1 6  7 8 9
# 2 1 NA 2 3

很好,这也是我最初想到的。虽然我认为你可以避免使用eval/parse;我用了:pmap_dfr(df, function(splitme, type){ as_tibble(setNames(as.list(strsplit(splitme, ", ")[[1]]), strsplit(type, ", ")[[1]]))})。但是separate_rows更好。 - cboettig
当然可以,但我认为在这里使用eval parse不是不良实践,因为我们一开始就将代码存储在字符中。 - moodymudskipper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接