изменение формата данных в больших данных в R - PullRequest
1 голос
/ 02 мая 2020

Я пытаюсь преобразовать свой длинный формат data.frame (5 столбцов: "person_id" "item_id" "item_type" "gender" "item_trans") в широкий формат, чтобы каждый person занимал только одну строку в data.frame.

У меня есть пробовал следующее безуспешно, есть ли быстрое исправление моего кода в BASE R ?

dat <- read.csv('https://raw.githubusercontent.com/izeh/n/master/n.csv', stringsAsFactors = F)

reshape(dat, dir = 'wide', idvar = c('person_id','gender'), timevar = 'item_type')

Ответы [ 2 ]

3 голосов
/ 02 мая 2020

Исходя из разъяснений ФП, это может быть

out <- reshape(dat[setdiff(names(dat), 'item_type')], idvar = c('person_id', 'gender'), direction = 'wide', timevar = 'item_id')
dim(out)
#[1]  2000 16006

out[1:3, c(1:3, 16000:16006)]
#   person_id gender item_trans.1 item_trans.15998 item_trans.15999 item_trans.16000 item_trans.16001 item_trans.16002 item_trans.16003
#1          1   MALE     5.091636               NA               NA               NA               NA               NA               NA
#32         2   MALE           NA               NA               NA               NA               NA               NA               NA
#64         3 FEMALE           NA               NA               NA               NA               NA               NA               NA
#   item_trans.16004
#1                NA
#32               NA
#64               NA
3 голосов
/ 02 мая 2020

Обновленный ответ с Base R - одна строка на человека

dat <- read.csv('https://raw.githubusercontent.com/izeh/n/master/n.csv', stringsAsFactors = F)

# sort the data by person_id, item_type and item_id
dat2 <- dat[order(dat$person_id,dat$item_type,dat$item_id),]

# h/t akrun for ave() approach to generate sequences
dat2$item_seq <- with(dat2, ave(seq_along(person_id), person_id,
                         item_type, FUN = seq_along))
dat2$item_type <- sprintf("%s_%02d",dat2$item_type,dat2$item_seq)
wide_dat <- reshape(dat2, dir = 'wide', drop = c("item_id","item_seq"), 
                    idvar = c('person_id','gender'),
                    timevar = 'item_type')
# clean up column names and print head()
names(wide_dat) <- gsub("item_trans.","",names(wide_dat))
head(wide_dat[1:6])

... и вывод:

> head(wide_dat[1:6])
    person_id gender audio_vocab_01 audio_vocab_02 audio_vocab_03 audio_vocab_04
3           1   MALE      1.5448298      1.6337223      0.4701200     3.04835834
36          2   MALE      3.0483583      3.1066522      3.0483583     3.04835834
64          3 FEMALE      1.6337223      1.6269504      1.0744742     1.62695041
97          4 FEMALE      3.0483583      1.6337223      1.0744742     1.36473950
141         5   MALE     -1.6627051      0.6117318     -0.7650658    -4.59511975
163         6  OTHER      0.1122673     -1.6627051      1.6337223    -0.02740973
> 

Обновленный ответ с одной строкой на person_id

dat <- read.csv('https://raw.githubusercontent.com/izeh/n/master/n.csv', stringsAsFactors = F)

library(tidyr)
library(dplyr)

dat %>%  arrange(person_id,item_type,item_id) %>%
     group_by(person_id,item_type) %>% 
     mutate(item_seq = seq_along(item_type)) %>%
     ungroup() %>% 
     mutate(item_type = sprintf("%s_%02d",item_type,item_seq)) %>%
     pivot_wider(id_cols = c("person_id", "gender"),
                    names_from = item_type,
                    values_from = item_trans) -> wide_dat

... и на выходе - фрейм данных с 2000 строками и 37 столбцами.

> head(wide_dat)
# A tibble: 6 x 37
  person_id gender audio_vocab_01 audio_vocab_02 audio_vocab_03 audio_vocab_04
      <int> <chr>           <dbl>          <dbl>          <dbl>          <dbl>
1         1 MALE            1.54           1.63           0.470         3.05  
2         2 MALE            3.05           3.11           3.05          3.05  
3         3 FEMALE          1.63           1.63           1.07          1.63  
4         4 FEMALE          3.05           1.63           1.07          1.36  
5         5 MALE           -1.66           0.612         -0.765        -4.60  
6         6 OTHER           0.112         -1.66           1.63         -0.0274
# … with 31 more variables: audio_vocab_05 <dbl>, audio_vocab_06 <dbl>,
#   ctest_01 <dbl>, ctest_02 <dbl>, ctest_03 <dbl>, ctest_04 <dbl>,
#   ctest_05 <dbl>, ctest_06 <dbl>, dictation_01 <dbl>, dictation_02 <dbl>,
#   dictation_03 <dbl>, dictation_04 <dbl>, dictation_05 <dbl>,
#   dictation_06 <dbl>, elicited_speech_01 <dbl>, elicited_speech_02 <dbl>,
#   elicited_speech_03 <dbl>, elicited_speech_04 <dbl>, elicited_speech_05 <dbl>,
#   elicited_speech_06 <dbl>, text_vocab_01 <dbl>, text_vocab_02 <dbl>,
#   text_vocab_03 <dbl>, text_vocab_04 <dbl>, text_vocab_05 <dbl>,
#   text_vocab_06 <dbl>, text_vocab_07 <dbl>, elicited_speech_07 <dbl>,
#   dictation_07 <dbl>, audio_vocab_07 <dbl>, ctest_07 <dbl>
> 

Исходный ответ

Ответ с использованием Tidyverse:

dat <- read.csv('https://raw.githubusercontent.com/izeh/n/master/n.csv', stringsAsFactors = F)

library(tidyr)
library(dplyr)
dat %>%  arrange(person_id,item_type,item_id) %>%
     group_by(person_id,item_type) %>% 
     mutate(item_seq = seq_along(item_type)) %>%
     pivot_wider(id_cols = c("person_id", "gender","item_type"),
                    names_from = item_seq,
                    names_prefix = "measurement",
                    values_from = item_trans) -> wide_dat

... и выходные данные:

> head(wide_dat)
# A tibble: 6 x 10
# Groups:   person_id, item_type [6]
  person_id gender item_type measurement1 measurement2 measurement3 measurement4
      <int> <chr>  <chr>            <dbl>        <dbl>        <dbl>        <dbl>
1         1 MALE   audio_vo…        1.54          1.63        0.470         3.05
2         1 MALE   ctest            0.904         2.20        1.39          1.67
3         1 MALE   dictation        5.09          5.09       -3.67          5.09
4         1 MALE   elicited…        1.83          1.07        2.39          2.27
5         1 MALE   text_voc…        2.39          3.68        2.32          1.97
6         2 MALE   audio_vo…        3.05          3.11        3.05          3.05
# … with 3 more variables: measurement5 <dbl>, measurement6 <dbl>,
#   measurement7 <dbl>
> 

Объяснение

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

Желаемый вывод - это широкоформатный фрейм данных, в котором каждая строка содержит три ключевые переменные (person_id, пол и item_type) и столбцы, представляющие наблюдения с первого по n-й для данного типа элемента.

Поскольку переменная item_id варьируется от 1 до 16 004, мы не можем использовать ее в качестве индекса для создания имен столбцов. Чтобы создать индекс, который будет варьироваться от 1 до максимального количества измерений, выполненных для каждой комбинации person_id и item_type, мы сортируем данные по person_id, item_type и item_id, добавляем group_by() и создайте последовательные числа для представления идентификатора измерения с помощью seq_along().

Вновь созданная индексная переменная item_seq варьируется от 1 до 7, максимальное количество уникальных измерений для комбинации person_id, item_type.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...