首页 > 解决方案 > 当某些列没有分隔符时,在 tidyr 中对许多列使用单独的行

问题描述

我有以下模拟数据集:

A <- c("Acura", "BMW", "Toyota", NA)
B <- c("1993;2004;2010", "2013", "2003;2011", NA)
C <- c("Blue;Black;Gold", "Silver", NA, NA)

df <- data.frame(A = A, B = B, C = C)

所以数据框看起来像这样:

> df
         A                B                 C
  1  Acura   1993;2004;2010   Blue;Black;Gold
  2    BMW             2013            Silver
  3 Toyota        2003;2011              <NA>
  4   <NA>             <NA>              <NA>

我想将数据集扩展到多行,所以它看起来像这样:

> new_df
          A         B          C
  1   Acura      1993       Blue
  2   Acura      2004      Black
  3   Acura      2010       Gold
  4     BMW      2013     Silver
  5  Toyota      2003       <NA>
  6  Toyota      2011       <NA>
  7    <NA>      <NA>       <NA>

我曾尝试使用 tidyr::separate_rows 但是我收到此错误,因为单独的行需要在每列中逐行使用相同数量的分隔符。这意味着,第 3 行(A = 丰田)是一个问题,因为该行的 C 列中有一个 NA,而不是像“NA;NA”这样的东西。这是我收到的命令和错误:

df %>% separate_rows(B, C, sep = ";", convert = TRUE)
   Error: All nested columns must have the same number of elements.

df[c(1:2,4),] %>% separate_rows(B, C, sep = ";", convert = TRUE)
      A    B      C
1 Acura 1993   Blue
2 Acura 2004  Black
3 Acura 2010   Gold
4   BMW 2013 Silver
5  <NA>   NA   <NA>

df[c(3),] %>% separate_rows(B, C, sep = ";", convert = TRUE)
    Error: All nested columns must have the same number of elements.

有人可以帮助如何实现 new_df 吗?!

标签: rstringdataframesplittidyr

解决方案


好的,最简单的解决方案可能是安装tidyr(0.8.3.9000) 的开发版本,因为它似乎已修复。用来devtools::install_github("tidyverse/tidyr")实现这一点。

但是,对于那些无法更新或不想使用包的预发布版本的人的解决方法,我们可以计算每行中所需的分隔符数量,并用分隔符填充列中的缺失值。这样就可以separate_rows工作并创建空字符串,然后我们将其替换为NA.

library(tidyverse)
A <- c("Acura", "BMW", "Toyota", NA)
B <- c("1993;2004;2010", "2013", "2003;2011", NA)
C <- c("Blue;Black;Gold", "Silver", NA, NA)
df <- data.frame(A = A, B = B, C = C, stringsAsFactors = FALSE)

df %>%
  mutate(seps = str_pad("", width = str_count(B, ";"), pad = ";")) %>%
  mutate_at(vars(B, C), ~ coalesce(., seps)) %>%
  separate_rows(B, C, sep = ";") %>%
  mutate_at(vars(B, C), ~ str_replace(., "^$", NA_character_))
#>        A    B      C seps
#> 1  Acura 1993   Blue   ;;
#> 2  Acura 2004  Black   ;;
#> 3  Acura 2010   Gold   ;;
#> 4    BMW 2013 Silver     
#> 5 Toyota 2003   <NA>    ;
#> 6 Toyota 2011   <NA>    ;
#> 7   <NA> <NA>   <NA> <NA>

reprex 包(v0.3.0)于 2019 年 7 月 1 日创建


推荐阅读