Мне было интересно, есть ли способ переформатировать мой DATA
в мой Desired_output
ниже?
Конкретно для каждого уникального study
мы склеиваем пару pre
и postNUMBER
вместе, отдельно для t
и c
.
Например, для study == 2
мы склеиваем пару pre
и postNUMBER
вместе, идя ОТ:
study time nt nc mt mc sdt sdc outcome
2 pre 38 48 1.89 2.22 0.40 0.76 fram
2 post1 38 48 4.07 2.52 2.20 1.58 fram
К:
study time group n mpre mpost sdpre sdpost outcome
2 pre-post1 t 38 1.89 4.07 0.40 2.20 fram
2 pre-post1 c 48 2.22 2.52 0.76 1.58 fram
пс. Если уникальный study
в DATA
не содержал pre
(состоял только из postNUMBER
) или postNUMBER
(состоял только из pre
), мы просто его опускаем.
DATA <- read.table(header=T, text = "
study time nt nc mt mc sdt sdc outcome
1 pre 28 58 0.89 1.22 1.40 1.76 Conv
1 post1 28 58 5.07 3.52 3.20 2.58 Conv
1 post2 28 58 3.64 2.86 3.15 2.80 Conv
2 pre 38 48 1.89 2.22 0.40 0.76 fram
2 post1 38 48 4.07 2.52 2.20 1.58 fram
3 post1 31 18 2.07 1.52 1.20 0.58 voca
3 post2 32 18 3.07 2.32 1.12 9.85 voca
")
Desired_output <- read.table(header=T, text = "
study time group n mpre mpost sdpre sdpost outcome
1 pre-post1 t 28 0.89 5.07 1.40 3.20 Conv
1 pre-post2 t 28 0.89 3.64 1.40 3.15 Conv
1 pre-post1 c 58 1.22 3.52 1.76 2.58 Conv
1 pre-post2 c 58 1.22 2.86 1.76 2.80 Conv
2 pre-post1 t 38 1.89 4.07 0.40 2.20 fram
2 pre-post1 c 48 2.22 2.52 0.76 1.58 fram
")
tidyverse
Предлагается pivot_longer()
в первый раз иметь по одной строке на каждую учебную группу (и столбец для n, m и sd). Во второй раз вы можете left_join
строки «опубликовать» (filter(time! = "pre"
) с «предварительными» строками (filter(time= = "pre"
); с соответствующим аргументом.
У меня select
несколько колонок. Обратите внимание, что я сохранил строку без pre
с некоторыми NA
; их можно отфильтровать, если вы хотите их исключить.
library(tidyverse)
DATA <- read.table(header=T, text = "
study time nt nc mt mc sdt sdc outcome
1 pre 28 58 0.89 1.22 1.40 1.76 Conv
1 post1 28 58 5.07 3.52 3.20 2.58 Conv
1 post2 28 58 3.64 2.86 3.15 2.80 Conv
2 pre 38 48 1.89 2.22 0.40 0.76 fram
2 post1 38 48 4.07 2.52 2.20 1.58 fram
3 post1 31 18 2.07 1.52 1.20 0.58 voca
3 post2 32 18 3.07 2.32 1.12 9.85 voca
")
data2 =
DATA %>% pivot_longer(nt:sdc,
names_to = c(".value","group"),
names_pattern = "(n|m|sd)(t|c)")
left_join(data2 %>% filter(time ! = "pre"),
data2 %>% filter(time = = "pre"),
by = c("study","group"),
suffix= c("post","pre") ) %>%
select(study, time = timepost, group, npre, npost, mpre, mpost, sdpre,sdpost,
outcome = outcomepost)
#> # A tibble: 10 × 10
#> study time group npre npost mpre mpost sdpre sdpost outcome
#> <int> <chr> <chr> <int> <int> <dbl> <dbl> <dbl> <dbl> <chr>
#> 1 1 post1 t 28 28 0.89 5.07 1.4 3.2 Conv
#> 2 1 post1 c 58 58 1.22 3.52 1.76 2.58 Conv
#> 3 1 post2 t 28 28 0.89 3.64 1.4 3.15 Conv
#> 4 1 post2 c 58 58 1.22 2.86 1.76 2.8 Conv
#> 5 2 post1 t 38 38 1.89 4.07 0.4 2.2 fram
#> 6 2 post1 c 48 48 2.22 2.52 0.76 1.58 fram
#> 7 3 post1 t NA 31 NA 2.07 NA 1.2 voca
#> 8 3 post1 c NA 18 NA 1.52 NA 0.58 voca
#> 9 3 post2 t NA 32 NA 3.07 NA 1.12 voca
#> 10 3 post2 c NA 18 NA 2.32 NA 9.85 voca
Created on 2024-05-07 with reprex v2.0.2
Использование join
потенциально может быть более элегантным, но вот подход без него. При необходимости может дать некоторую регулировку.
Подготовка ДАННЫХ путем filter
обработки исследований без pre и добавления групп в pre, чтобы можно было назначать pre и postX в случае, если postX больше.
library(dplyr)
library(tidyr)
library(stringr)
DATA_prep <- DATA %>%
filter(any(time == "pre"), .by = study) %>%
mutate(pgrp = if_else(time == "pre",
max(as.numeric(str_extract(time, ".+(\\d+)$",
group=1)), na.rm=T), 1),
grp = time == "pre", .by = study) %>%
uncount(pgrp) %>%
mutate(time = if_else(time == "pre", paste0(time, cumsum(grp)), time),
grp = sub(".*(\\d+)$", "\\1", time), .by = c(study, grp))
summarize
обработка и unnest
обработка данных посредством групповой ассоциации, сгенерированной из имен переменных в более длинной форме.
library(rlang)
DATA_prep %>%
pivot_longer(-c(study, time, outcome, grp)) %>%
mutate(group = sub(".*(.$)", "\\1", name),
name = sub("^(.*)[tc]$", "\\1", name)) %>%
pivot_wider() %>%
mutate(m = set_names(m, sub("\\d+", "", time)),
sd = set_names(sd, sub("\\d+", "", time))) %>%
summarize(time = paste(time, collapse = "-"),
m = list(m),
sd = list(sd),
outcome = unique(outcome), .by = c(study, group, grp, n)) %>%
unnest_wider(c(m, sd), names_sep = "") %>%
select(-grp)
выход
study group n time mpre mpost sdpre sdpost outcome
<int> <chr> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr>
1 1 t 28 pre1-post1 0.89 5.07 1.4 3.2 Conv
2 1 c 58 pre1-post1 1.22 3.52 1.76 2.58 Conv
3 1 t 28 pre2-post2 0.89 3.64 1.4 3.15 Conv
4 1 c 58 pre2-post2 1.22 2.86 1.76 2.8 Conv
5 2 t 38 pre1-post1 1.89 4.07 0.4 2.2 fram
6 2 c 48 pre1-post1 2.22 2.52 0.76 1.58 fram