【问题标题】:How to pull multiple rows into columns?如何将多行拉入列?
【发布时间】:2019-10-11 13:34:21
【问题描述】:

考虑以下数据框:

data_frame(
col1 = c("2017", "June",   "New", 10, 30),
col2 = c("2018", "July",   "Old", 20, 50),
name = c(NA, NA, NA, "dog", "cat")
)

# A tibble: 5 x 3
  col1  col2  name 
1 2017  2018  NA   
2 June  July  NA   
3 New   Old   NA   
4 10    20    dog  
5 30    50    cat  

我想把它转换成这个输出:

## Year Month  Type name Amount
## 2017 June   New  dog  10
## 2018 July   Old  dog  20
## 2017 June   New  cat  30
## 2018 July   Old  cat  50

我尝试过更长时间地使用枢轴,但它很难处理多个 以及处理 NA 的死区。

【问题讨论】:

  • 也许我的咖啡还没有开始,但我没有遵循重塑这一点的逻辑。您如何将名称列与其他列匹配,以及您对 NA 的计划是什么?
  • 你实际上有两个不同的数据集在两个不同的方向上挤在一起。 Year/Month/Type 数据按行排列,然后是两行 dog/cat 数据按列排列。需要大量的特殊处理才能将它们分开并将它们重新格式化为更可行的东西,以至于我怀疑您的示例的解决方案是否适用于更大的数据集。 TLDR;您需要先分离和/或重新格式化源数据,然后再尝试对其进行转换。

标签: r dplyr tidyr


【解决方案1】:

我通过识别 3 种类型的数据来解决这个问题,这些数据都被粉碎到一个数据框中,然后将它们分开。就像上面的 @jdobres 所说,这可能不会超出这个玩具示例,但应该是一个开始。

据我所知,您可以根据col1 中的正则表达式搜索提取 3 种类型的数据:

  1. 年份,由 ^20\\d{2}$ 标识(如果包含 19xx 年等,则需要调整
  2. 月份,由非数字字符标识
  3. 名称,由col1 中的值类型或非NA name 标识

过滤并重塑它们,使它们的数据与您想要的输出中显示的形状相匹配:

library(dplyr)
library(tidyr)

yrs_df <- df %>% 
  filter(grepl("^20\\d{2}$", col1)) %>%
  gather(key, value = year) %>%
  filter(!is.na(year))

name_df <- df %>%
  filter(!is.na(name)) %>%
  gather(key, value, -name)

第二次重新调整月份,因为 monthtype 在同一列中,并且还想将它们分开。

month_df <- df %>%
  filter(grepl("^\\D", col1)) %>%
  mutate(col_type = row_number()) %>%
  gather(key, value, -col_type) %>%
  filter(!is.na(value)) %>%
  spread(key = col_type, value, sep = "") %>%
  rename(month = col_type1, type = col_type2)

yrs_df
#> # A tibble: 2 x 2
#>   key   year 
#>   <chr> <chr>
#> 1 col1  2017 
#> 2 col2  2018
name_df
#> # A tibble: 4 x 3
#>   name  key   value
#>   <chr> <chr> <chr>
#> 1 dog   col1  10   
#> 2 cat   col1  30   
#> 3 dog   col2  20   
#> 4 cat   col2  50
month_df
#> # A tibble: 2 x 3
#>   key   month type 
#>   <chr> <chr> <chr>
#> 1 col1  June  New  
#> 2 col2  July  Old

然后按键连接所有内容(也可以使用purrr::reduce,因为所有连接都在同一列上)

yrs_df %>%
  inner_join(month_df, by = "key") %>%
  inner_join(name_df, by = "key")
#> # A tibble: 4 x 6
#>   key   year  month type  name  value
#>   <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 col1  2017  June  New   dog   10   
#> 2 col1  2017  June  New   cat   30   
#> 3 col2  2018  July  Old   dog   20   
#> 4 col2  2018  July  Old   cat   50

综上所述——这里可能存在一个更大的问题,它会像这样将你的所有数据混在一起,而这些数据可以在上游进一步解决。

【讨论】:

  • 这是一个糟糕的文件,我知道。我真正喜欢你的方法的地方在于它非常简单——拆开并清洁每一块。我试图在一个管道中做太多事情!
猜你喜欢
  • 1970-01-01
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 2019-08-29
  • 2012-08-01
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
相关资源
最近更新 更多