R как конвертировать из длинного в широкий формат - PullRequest
1 голос
/ 01 ноября 2019

Мне требуется фрейм данных df_wide со следующими столбцами:

userID   SAT   GRE   task_conf task_chall active_conf  active_chall  sleep_conf  sleep_chall morn_conf  morn_chall
30798    A     1400  2         3          5            2             6            1          4          2
30895    A     1200  6         2          5            3             5            2          5          3
32678    B     1000  5         3          6            3             6            2          5          2
34679    A     1300  4         3          4            2             6            1          6          3
35999    A     1400  2         2          2            2             2            2          2          2

Некоторые сведения о функциях:

The variables '_conf' and '_chall' contain integer values between 1 and 6
'userID's can be factors or integers but they are not continuous numbers
SAT represents the grade of that 'userID'
GRE represents the score of that 'userID'
SAT and GRE always stay the same for a given 'userID' 

Мои исходные данные df_long в настоящее время находятся в следующихform:

userID SAT GRE  action ConfChall vals
30798  A   1400 task   conf      2
30798  A   1400 task   chall     3
30798  A   1400 active conf      5
30798  A   1400 active chall     2
30798  A   1400 sleep  conf      6
30798  A   1400 sleep  chall     1
30798  A   1400 morn   conf      4
30798  A   1400 morn   chall     2
30895  A   1200 task   conf      6
30895  A   1200 task   chall     2
30895  A   1200 active conf      5
30895  A   1200 active chall     3
30895  A   1200 sleep  conf      5
30895  A   1200 sleep  chall     2
30895  A   1200 morn   conf      5
30895  A   1200 morn   chall     3
32678  B   1000 task   conf      5
32678  B   1000 task   chall     3
32678  B   1000 active conf      6
32678  B   1000 active chall     3
32678  B   1000 sleep  conf      6
32678  B   1000 sleep  chall     2
32678  B   1000 morn   conf      5
32678  B   1000 morn   chall     2
34679  A   1300 task   conf      4
34679  A   1300 task   chall     3
34679  A   1300 active conf      4
34679  A   1300 active chall     2
34679  A   1300 sleep  conf      6
34679  A   1300 sleep  chall     1
34679  A   1300 morn   conf      6
34679  A   1300 morn   chall     3
35999  A   1400 task   conf      2
35999  A   1400 task   chall     2
35999  A   1400 active conf      2
35999  A   1400 active chall     2
35999  A   1400 sleep  conf      2
35999  A   1400 sleep  chall     2
35999  A   1400 morn   conf      2
35999  A   1400 morn   chall     2

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

library(reshape2)
df_wide = recast(df_long, userID ~ c('action','confChall','vals'),
          id.var = c("userID", "SAT", "GRE"))

df_wide = dcast(df_long, userID + SAT + GRE ~ c(action + ConfChall), value.var = "vals")

Я пытался следовать примерам кодов со следующих страниц. Но я испытываю трудности в применении их к моей проблеме. Будем весьма благодарны за любые советы или предложения по этому вопросу.

Изменение данных из длинного в широкий формат - более одной переменной

Изменение нескольких значений одновременно

1 Ответ

2 голосов
/ 01 ноября 2019

Вы можете изменить несколько столбцов категории и нескольких столбцов значений с помощью pivot_wider из пакета tidyr (который входит в комплект tidyverse пакетов):

library(tidyverse)

df_wide = df_long %>% 
  pivot_wider(names_from=c(action, ConfChall), values_from=vals)
  userID SAT  GRE task_conf task_chall active_conf active_chall sleep_conf sleep_chall morn_conf morn_chall
1  30798   A 1400         2          3           5            2          6           1         4          2
2  30895   A 1200         6          2           5            3          5           2         5          3
3  32678   B 1000         5          3           6            3          6           2         5          2
4  34679   A 1300         4          3           4            2          6           1         6          3

reshape2 - это старый пакет, который, насколько я знаю, больше не находится в активной разработке и был заменен tidyverse пакетами.

Для устранения предупреждения, которое вы упомянули вкомментарии: если в широком фрейме данных есть какие-либо ячейки, имеющие более одного значения, то вы получите полученный результат. Это произойдет в вашем случае, когда существует более одной строки с одним и тем же идентификатором пользователя, SAT, GRE, action и ConfChall, или вообще, когда они представляют собой комбинации категорий строк и столбцов, которые могут появляться в более чем одной строке. Этого не происходит в вашем образце данных, но это происходит в ваших реальных данных.

Итак, давайте добавим дублированную строку к вашему образцу данных:

df_long = read.table(text="userID SAT GRE  action ConfChall vals
30798  A   1400 task   conf      2
30798  A   1400 task   chall     3
30798  A   1400 task   chall     4 # added row to create a duplicate
30798  A   1400 active conf      5
30798  A   1400 active chall     2
30798  A   1400 sleep  conf      6
30798  A   1400 sleep  chall     1
30798  A   1400 morn   conf      4
30798  A   1400 morn   chall     2
30895  A   1200 task   conf      6
30895  A   1200 task   chall     2
30895  A   1200 active conf      5
30895  A   1200 active chall     3
30895  A   1200 sleep  conf      5
30895  A   1200 sleep  chall     2
30895  A   1200 morn   conf      5
30895  A   1200 morn   chall     3
32678  B   1000 task   conf      5
32678  B   1000 task   chall     3
32678  B   1000 active conf      6
32678  B   1000 active chall     3
32678  B   1000 sleep  conf      6
32678  B   1000 sleep  chall     2
32678  B   1000 morn   conf      5
32678  B   1000 morn   chall     2
34679  A   1300 task   conf      4
34679  A   1300 task   chall     3
34679  A   1300 active conf      4
34679  A   1300 active chall     2
34679  A   1300 sleep  conf      6
34679  A   1300 sleep  chall     1
34679  A   1300 morn   conf      6
34679  A   1300 morn   chall     3", header=TRUE)

Теперь давайте снова изменим ширину,Обратите внимание, что мы получаем предупреждение и что одна из ячеек столбца списка имеет два значения вместо одного:

df_long %>% 
  pivot_wider(names_from=c(action, ConfChall), values_from=vals)

Warning message:
Values in `vals` are not uniquely identified; output will contain list-cols.
* Use `values_fn = list(vals = list)` to suppress this warning.
* Use `values_fn = list(vals = length)` to identify where the duplicates arise
* Use `values_fn = list(vals = summary_fun)` to summarise duplicates 
  userID SAT     GRE   task_conf  task_chall active_conf active_chall  sleep_conf sleep_chall   morn_conf  morn_chall
   <int> <fct> <int> <list<int>> <list<int>> <list<int>>  <list<int>> <list<int>> <list<int>> <list<int>> <list<int>>
1  30798 A      1400         [1]         [2]         [1]          [1]         [1]         [1]         [1]         [1]
2  30895 A      1200         [1]         [1]         [1]          [1]         [1]         [1]         [1]         [1]
3  32678 B      1000         [1]         [1]         [1]          [1]         [1]         [1]         [1]         [1]
4  34679 A      1300         [1]         [1]         [1]          [1]         [1]         [1]         [1]         [1]

Чтобы получить обычный фрейм данных, вы можете использовать unnest(). Обратите внимание, что теперь есть пять строк, с идентификатором пользователя 30798, появляющимся дважды:

df_long %>% 
  pivot_wider(names_from=c(action, ConfChall), values_from=vals) %>% 
  unnest()
  userID SAT     GRE task_conf task_chall active_conf active_chall sleep_conf sleep_chall morn_conf morn_chall
   <int> <fct> <int>     <int>      <int>       <int>        <int>      <int>       <int>     <int>      <int>
1  30798 A      1400         2          3           5            2          6           1         4          2
2  30798 A      1400         2          4           5            2          6           1         4          2
3  30895 A      1200         6          2           5            3          5           2         5          3
4  32678 B      1000         5          3           6            3          6           2         5          2
5  34679 A      1300         4          3           4            2          6           1         6          3

Если вы хотите, чтобы дублирующие строки каким-то образом суммировались, так что вы получите только одну строкуДля каждой комбинации переменных строки и столбца вы можете применить функцию суммирования. Ниже мы берем среднее значение для каждой ячейки, которое в данном случае влияет только на одну ячейку с двумя строками данных:

df_long %>% 
  pivot_wider(names_from=c(action, ConfChall), values_from=vals,
              values_fn=list(vals=mean))
  userID SAT     GRE task_conf task_chall active_conf active_chall sleep_conf sleep_chall morn_conf morn_chall
   <int> <fct> <int>     <dbl>      <dbl>       <dbl>        <dbl>      <dbl>       <dbl>     <dbl>      <dbl>
1  30798 A      1400         2        3.5           5            2          6           1         4          2
2  30895 A      1200         6        2             5            3          5           2         5          3
3  32678 B      1000         5        3             6            3          6           2         5          2
4  34679 A      1300         4        3             4            2          6           1         6          3
...