Разверните значения столбца R до заголовков столбцов со значениями другого столбца - PullRequest
3 голосов
/ 22 мая 2019

Я пытаюсь расширить таблицу данных R, которая выглядит следующим образом:

a   step_num   duration 

1          1          5 
1          2          4
1          3          1
2          1          7
2          2          2
2          3          9
3          1          1
3          2          1
3          3          3

На что-то похожее на это:

a | step_num | duration | 1_duration | 2_duration | 3_duration |
----------------------------------------------------------------
1          1          5            5           -            -
1          2          4            -           4            -
1          3          1            -           -            1
2          1          7            7           -            -
2          2          2            -           2            -
2          3          9            -           -            9
3          1          1            1           -            -
3          2          1            -           1            -
3          3          3            -           -            3

Мне интересно, есть лиФункция «расширения», так сказать, что бы сделать это.

Спасибо!

Ответы [ 4 ]

3 голосов
/ 22 мая 2019

Или опция с dcast из data.table

library(data.table)
dcast(setDT(df),  a + step_num ~  
        paste0("duration_", step_num), value.var = 'duration')
#    a step_num duration_1 duration_2 duration_3
#1: 1        1          5         NA         NA
#2: 1        2         NA          4         NA
#3: 1        3         NA         NA          1
#4: 2        1          7         NA         NA
#5: 2        2         NA          2         NA
#6: 2        3         NA         NA          9
#7: 3        1          1         NA         NA
#8: 3        2         NA          1         NA
#9: 3        3         NA         NA          3

ПРИМЕЧАНИЕ. Лучше иметь NA вместо -, поскольку NA легко удаляется с помощью is.na/complete.cases/na.omit, и это не приведет к изменению класса столбца на character

данные

df <- structure(list(a = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), step_num = c(1L, 
2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), duration = c(5L, 4L, 1L, 7L, 
2L, 9L, 1L, 1L, 3L)), class = "data.frame", row.names = c(NA, 
-9L))
3 голосов
/ 22 мая 2019

Мы можем сделать это в base r .

cbind(df,
      reshape(df, idvar = c("a","step_num"), timevar = "step_num", direction = "wide")[,-1])

#>   a step_num duration duration.1 duration.2 duration.3
#> 1 1        1        5          5         NA         NA
#> 2 1        2        4         NA          4         NA
#> 3 1        3        1         NA         NA          1
#> 4 2        1        7          7         NA         NA
#> 5 2        2        2         NA          2         NA
#> 6 2        3        9         NA         NA          9
#> 7 3        1        1          1         NA         NA
#> 8 3        2        1         NA          1         NA
#> 9 3        3        3         NA         NA          3

Создано в 2019-05-21 с помощью пакета представительства (v0.2.1)

2 голосов
/ 22 мая 2019

Вот подход с использованием dplyr и tidyr.

Мы берем исходные данные и добавляем некоторые столбцы, сначала добавляя новый столбец col, который содержит нужный заголовок столбца на основе step_num. Затем мы используем tidyr::spread, чтобы поместить длительности в разные столбцы, в зависимости от того, с какими col они идут. fill = "-" заполняет все пустые столбцы тире. Наконец, мы удаляем столбцы a и step_num, поскольку они уже есть в исходных данных, и мы не хотим иметь их копии.

(Обратите внимание, нам нужно было step_num, чтобы все еще существовать на шаге spread, потому что мы хотели, чтобы каждая строка была выровнена с исходными строками. Без step_num данные были бы распространены в более широкий и короткий формат это бы выровняло строки.)

library(dplyr); library(tidyr)
df %>%  
  mutate(col = paste0(step_num, "_duration")) %>%
  spread(col, duration, fill = "-") %>%
  select(-a, -step_num)) %>% 
  bind_cols(df, .)  # Edit, per excellent suggestion from M-M


  a step_num duration 1_duration 2_duration 3_duration
1 1        1        5          5          -          -
2 1        2        4          -          4          -
3 1        3        1          -          -          1
4 2        1        7          7          -          -
5 2        2        2          -          2          -
6 2        3        9          -          -          9
7 3        1        1          1          -          -
8 3        2        1          -          1          -
9 3        3        3          -          -          3
1 голос
/ 22 мая 2019

Простое tidyverse решение:

library(tidyverse)

df %>%
  mutate(step = step_num) %>%
  spread(step, duration, fill = '-') %>%
  rename_all( ~ gsub('(\\d+)', 'duration_\\1', .))

#   a step_num duration_1 duration_2 duration_3
# 1 1        1          5          -          -
# 2 1        2          -          4          -
# 3 1        3          -          -          1
# 4 2        1          7          -          -
# 5 2        2          -          2          -
# 6 2        3          -          -          9
# 7 3        1          1          -          -
# 8 3        2          -          1          -
# 9 3        3          -          -          3
...