преобразовать данные с двумя столбцами временных рядов - PullRequest
1 голос
/ 13 апреля 2020

У меня есть такие данные, что есть набор столбцов идентификаторов, а затем несколько значений временных рядов.

data.frame(id = c("x", "y", "z"),
             year_1_a = c(1, 2, 3),
             year_2_a = c(4, 5, 6),
             year_1_b = c(6, 7, 8),
             year_2_b = c(3, 4, 5), stringsAsFactors = F)

Я ищу способ преобразовать данные в более длинный формат, в котором идентификатор будет дублируется, в качестве ключа будет новый столбец, и у меня будет только один «набор» лет со значениями.

Ожидаемый результат:

  data.frame(id = c("x","x", "y", "y", "z", "z"),
             key = c('a', 'b'),
             year_1 = c(1, 6, 2, 7, 3, 8),
             year_2 = c(4, 3, 5, 4, 6, 5), stringsAsFactors = F)

Я искал pivot_longer но это делает код слишком длинным со строкой для каждого года и значения. Я думаю, что лучший способ - это разделить данные на две dfs, а затем rbind, но мне было интересно, есть ли лучший способ без создания промежуточных фреймов данных.

1 Ответ

2 голосов
/ 13 апреля 2020

Мы можем использовать pivot_longer из tidyr, указав names_sep в качестве _, за которым следуют буквы в конце ($) имени

library(dplyr)
library(tidyr)
out1 <- df %>% 
    pivot_longer(cols = -id, names_to = c('.value', 'key'), 
        names_sep="_(?=[a-z]$)")
out1
# A tibble: 6 x 4
#  id    key   year_1 year_2
#  <chr> <chr>  <dbl>  <dbl>
#1 x     a          1      4
#2 x     b          6      3
#3 y     a          2      5
#4 y     b          7      4
#5 z     a          3      6
#6 z     b          8      5

-проверка с выходом OP

all.equal(out1, out, check.attributes = FALSE)
#[1] TRUE

Или с melt с data.table

library(data.table)
out2 <- melt(setDT(df), measure = patterns('year_1', 'year_2'),
      value.name = c('year_1', 'year_2'), variable.name = 'key')

Или с reshape с base R

reshape(df, idvar = 'id', direction = 'long', varying = list(c(2, 4), c(3, 5)))
...