R разворачивает несколько столбцов в длинный формат - PullRequest
0 голосов
/ 16 апреля 2020

У меня есть широкоформатный фрейм данных на уровне человека, который я пытаюсь объединить в сводную таблицу длинного формата. Пример кода и примеры приведены ниже:

set.seed(100)

#Original wide format person level data
dat_wide <- tibble(group = rep(x = c('a','b','c'), each = 5),
                   d1 = sample(x = c(1, 0, NA_integer_), size = 15, replace = TRUE),
                   d2 = sample(x = c(1, 0, NA_integer_), size = 15, replace = TRUE),
                   d3 = sample(x = c(1, 0, NA_integer_), size = 15, replace = TRUE)) %>% 
  mutate(d1_br = case_when(
    d1 == 1 ~ .8,
    d1 == 0 ~ .2,
    TRUE ~ NA_real_
  ),
  d2_br = case_when(
    d2 == 1 ~ .6,
    d2 == 0 ~ .4,
    TRUE ~ NA_real_
  ),
  d3_br = case_when(
    d3 == 1 ~ .95,
    d3 == 0 ~ .05,
    TRUE ~ NA_real_
  ))
dat_wide

# A tibble: 15 x 7
   group    d1    d2    d3 d1_br d2_br d3_br
   <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 a         0    NA     0   0.2  NA    0.05
 2 a         1     0     0   0.8   0.4  0.05
 3 a         1    NA     1   0.8  NA    0.95
 4 a         1    NA    NA   0.8  NA   NA   
 5 a         0    NA     1   0.2  NA    0.95
 6 b        NA     0     1  NA     0.4  0.95
 7 b        NA    NA     1  NA    NA    0.95
 8 b        NA     0     1  NA     0.4  0.95
 9 b         1     0     0   0.8   0.4  0.05
10 b         1     1    NA   0.8   0.6 NA   
11 c         0    NA     1   0.2  NA    0.95
12 c         0    NA     0   0.2  NA    0.05
13 c        NA    NA     1  NA    NA    0.95
14 c         1    NA     0   0.8  NA    0.05
15 c         0     1     0   0.2   0.6  0.05

#Long format summary table
dat_long <- tibble(group = rep(c('a','b','b'), each = 9),
                   dv = rep(c('d1','d2','d3'), each = 3, times = 3),
                   response = rep(c(1, 0, NA_integer_), times = 9)) %>% 
  mutate(br = case_when(
    dv == 'd1' & response == 1 ~ .8,
    dv == 'd1' & response == 0 ~ .2,
    dv == 'd2' & response == 1 ~ .6,
    dv == 'd2' & response == 0 ~ .4,
    dv == 'd3' & response == 1 ~ .95,
    dv == 'd3' & response == 0 ~ .05,
    TRUE ~ NA_real_
  ))

# A tibble: 27 x 4
   group dv    response    br
   <chr> <chr>    <dbl> <dbl>
 1 a     d1           1  0.8 
 2 a     d1           0  0.2 
 3 a     d1          NA NA   
 4 a     d2           1  0.6 
 5 a     d2           0  0.4 
 6 a     d2          NA NA   
 7 a     d3           1  0.95
 8 a     d3           0  0.05
 9 a     d3          NA NA   
10 b     d1           1  0.8 
# ... with 17 more rows

Я вполне уверен, что этого можно добиться с помощью tidyr::pivot_longer, хотя я новичок в его использовании и не понял всех его возможностей. Должно работать что-то похожее на следующее, но может ли кто-нибудь помочь заполнить синтаксис pivot_longer? Нужны ли мне аргументы names_sep или names_prefix? Я еще не обнял их.

#Possible solution
dat_long <- dat_wide %>% 
  # pivot_longer(...) %>% 
  distinct(group, dv, response, .keep_all = TRUE)

1 Ответ

1 голос
/ 16 апреля 2020

Это может быть проще, если у вас последовательно есть числовые значения в именах столбцов. Если вы переименуете dat_wide:

names(dat_wide) <- sub("(\\w+)(\\d+)(\\w*)", "\\1\\3\\2", names(dat_wide))

d1_br станет d_br1 et c.

Тогда вы можете использовать pivot_longer с двумя наборами столбцов:

library(tidyverse)

dat_wide %>%
  pivot_longer(cols = -group, 
               names_to = c(".value", "dv"),
               names_pattern = "(\\w+)(\\d+)") %>%
  distinct(group, dv, d, .keep_all = TRUE) %>%
  arrange(group, dv)

Выход

# A tibble: 24 x 4
   group dv        d  d_br
   <chr> <chr> <dbl> <dbl>
 1 a     1         0  0.2 
 2 a     1        NA NA   
 3 a     1         1  0.8 
 4 a     2        NA NA   
 5 a     2         0  0.4 
 6 a     2         1  0.6 
 7 a     3        NA NA   
 8 a     3         0  0.05
 9 a     3         1  0.95
10 b     1         0  0.2 
...