Как я могу организовать код в длинном формате в зависимости от времени измерения

#r #format

Вопрос:

У меня есть вопрос о преобразовании фрейма данных из широкого формата в длинный формат. Я не нашел никаких решений, которые соответствовали бы моему фрейму данных. У нас было три временных интервала измерения с одними и теми же анкетами (например, PANAS и еще две анкеты). Мой фрейм данных сейчас выглядит так:

 | code| PANAS_1| PANAS_2| PANAS1_1| PANAS1_2| PANAS2_1| PANAS2_2|

|CAPQ |   4    |    3   |    1    |   5     |    2    |    4   |

|BANI |   2    |    3   |    4    |   4     |    3    |    2   |
 

Я хочу поместить его в формат, который выглядит следующим образом:

 | code| timeslot| PANAS_1| PANAS_2 | 

|CAPQ |   1     |    4   |    3    |   
|CAPQ |   2     |    1   |    5    |  
|CAPQ |   3     |    2   |    4    | 
  
|BANI |   1     |    2   |    3    |  
|BANI |   2     |    4   |    4    |   
|BANI |   3     |    3   |    2    |  
 

Я пытался melt() , но я просто не знаю, что делать, потому что имена переменных в анкетах не совпадают (имена переменных в первом временном интервале просто «PANAS_1», во втором временном интервале начинаются с 1 «PANAS1_1», а в третьем временном интервале начинаются с 2 «PANAS2_1). Кроме того, у меня нет переменной, которая объясняет, в каком состоянии временного интервала находятся элементы.

Я надеюсь, что вы поймете мою проблему и поможете мне ее решить. Если вам нужна дополнительная информация, просто дайте мне знать.

Ответ №1:

Вот используемый подход data.table . С melt.data.table() помощью вы можете использовать группы measure.vars. В этом случае вы можете использовать patterns() для поиска групп по их суффиксу.

 library(data.table)

df <- read.table(text = "code| PANAS_1| PANAS_2| PANAS1_1| PANAS1_2| PANAS2_1| PANAS2_2
CAPQ |   4    |    3   |    1    |   5     |    2    |    4   
BANI |   2    |    3   |    4    |   4     |    3    |    2   
", sep = "|", header = TRUE)

setDT(df)

DT.long <- melt(df,
                id.vars = "code",
                measure.vars = patterns("_1", "_2"),
                variable.name = "timeslot",
                value.name = c("PANAS_1", "PANAS_2")
                )[order(code), ]

DT.long
#>     code timeslot PANAS_1 PANAS_2
#> 1: BANI         1       2       3
#> 2: BANI         2       4       4
#> 3: BANI         3       3       2
#> 4: CAPQ         1       4       3
#> 5: CAPQ         2       1       5
#> 6: CAPQ         3       2       4
 

Создано 2021-08-19 пакетом reprex (v2.0.1)

Ответ №2:

Вот один из используемых подходов tidyverse . Вы можете использовать pivot_longer , чтобы поместить в длинный формат и отделить последнее число после подчеркивания. Затем вы можете добавить timeslot переменную для каждой code комбинации /чисел, предполагая, что времена в порядке. Наконец, вы можете вернуться к широкому формату с pivot_wider (или оставить как есть для дальнейшей обработки/анализа).

 library(tidyverse)

df %>%
  pivot_longer(cols = -code, names_to = c("var", "PANAS"), names_sep = "_") %>%
  group_by(code, PANAS) %>%
  mutate(timeslot = 1:n()) %>%
  pivot_wider(id_cols = c(code, timeslot), names_from = PANAS, names_prefix = "PANAS_", values_from = value)
 

Выход

   code  timeslot PANAS_1 PANAS_2
  <chr>    <int>   <dbl>   <dbl>
1 CAPQ         1       4       3
2 CAPQ         2       1       5
3 CAPQ         3       2       4
4 BANI         1       2       3
5 BANI         2       4       4
6 BANI         3       3       2
 

Кроме того, вы можете переименовать имена столбцов и явно указать время внутри них:

 names(df) <- c("code", paste("PANAS", rep(1:3, each = 2), rep(1:2, times = 3), sep = "_"))

df %>%
  pivot_longer(cols = -code, names_to = c("timeslot", "PANAS"), names_pattern = "PANAS_(\d )_(\d )") %>%
  pivot_wider(id_cols = c(code, timeslot), names_from = PANAS, names_prefix = "PANAS_", values_from = value)