как собрать 2 набора столбцов в тайдыре

У меня есть следующая структура:

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_"))

но это не относится к году. Я просмотрел Соберите несколько наборов столбцов

но я не получаю команды распространения извлечения.


person KillerSnail    schedule 26.08.2015    source источник
comment
как мне генерировать случайные строки для проверки?   -  person KillerSnail    schedule 26.08.2015
comment
да исправлена ​​команда вставки   -  person KillerSnail    schedule 26.08.2015


Ответы (1)


Если мы используем gather, мы можем сделать это в два этапа. Во-первых, мы изменяем формат с «широкого» на «длинный» для имен столбцов, начинающихся с «категории», а на следующем шаге мы делаем то же самое с числовыми именами столбцов, выбирая с помощью matches. 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 и указываем patterns with в аргументе measure. У нас также есть возможность изменить имена столбцов столбца «значение». Столбец «переменная» имеет значение NULL, поскольку в ожидаемом выводе он не нужен.

library(data.table)#v1.9.5+
melt(setDT(df), measure=patterns(c('^category', '^[0-9]+$')), 
           value.name=c('category', 'year'))[, variable:=NULL][]
person akrun    schedule 26.08.2015
comment
аккуратная версия дает неверный результат - person Nettle; 07.10.2018