我如何在 tidyr 中收集 2 组列

how do I gather 2 sets of columns in tidyr

我有以下结构:

key | category_x | 2009 | category_y | 2010
test

请求的示例数据

set.seed(24)
df <- data.frame(
key = 1:10,
category_x = paste0("stock_", 0:9),
'2008' = rnorm(10, 0, 10),
category_y = paste0("stock_", 0:9),
'2009' = rnorm(10, 0, 10),
category_z = paste0("stock_", 0:9),
'2010' = rnorm(10, 0, 10),
check.names=FALSE
)

如何将其更改为:

key | category | year

我知道我可以使用:

library(magrittr)
library(dplyr)
library(tidyr)

data %>% gather(key, category, starts_with("category_"))

但这与年份无关。 我看了Gather multiple sets of columns

但我没有得到提取传播命令。

如果我们使用gather,我们可以分两步完成。首先,我们将以 'category' 开头的列名从 'wide' 格式重塑为 'long' 格式,在下一步中,我们通过选择 [=13] 对数字列名执行相同的操作=]. matches 可以正则表达式模式,所以 ^[0-9]+$ 的模式意味着我们匹配一个或多个数字 ([0-9]+) 从开始 (^) 到结束 ($) 的字符串。我们可以使用 select.

删除不需要的列
library(tidyr)
library(dplyr) 
gather(df, key, category, starts_with('category_')) %>%
     gather(key2, year, matches('^[0-9]+$')) %>%
     select(-starts_with('key'))

或者使用 data.table 的开发版本,这会容易得多,因为 melt 可以为 measure 列采用多种模式。我们将 'data.frame' 转换为 'data.table' (setDT(df)),使用 melt 并在 measure 参数中指定 patterns。我们还可以选择更改 'value' 列的列名。 'variable' 列设置为 NULL,因为在预期输出中不需要它。

library(data.table)#v1.9.5+
melt(setDT(df), measure=patterns(c('^category', '^[0-9]+$')), 
           value.name=c('category', 'year'))[, variable:=NULL][]