【问题标题】:R how to convert from long to wide formatR如何从长格式转换为宽格式
【发布时间】:2019-10-31 22:33:40
【问题描述】:

我需要一个带有以下列的数据框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目前格式如下:

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")

我尝试遵循以下页面中的示例代码。但是我很难将这些应用于我的问题。对此的任何建议或建议将不胜感激。

Reshape data from long to wide format - more than one variable

Reshape multiple values at once

【问题讨论】:

  • ?reshape2::melt

标签: r dplyr reshape reshape2


【解决方案1】:

您可以使用来自tidyr 包(属于tidyverse 包套件的一部分)中的pivot_wider 重塑多个类别列和多个值列:

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 包取代。

解决您在 cmets 中提到的警告:如果宽数据框中的任何单元格具有多个值,那么您将得到您得到的结果。当有不止一行具有相同的用户 ID、SAT、GRE、操作和 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()。请注意,现在有五行,用户 ID 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

【讨论】:

  • 谢谢@eipi10 我试过了,我收到以下警告消息:警告消息:vals 中的值不是唯一标识的;输出将包含列表列。 * 使用values_fn = list(vals = list) 抑制此警告。 * 使用values_fn = list(vals = length) 确定重复出现的位置 * 使用values_fn = list(vals = summary_fun) 总结重复 我需要采取行动和ConfChall 作为因素吗?
  • 在你的真实数据中,是否至少有一个 userID、SAT 和 GRE 的组合出现了多次?
  • 是的,在我原来的df_long 数据中,大部分userIDs 都在不止一行上。
  • SATGRE 对于给定的userID 保持不变。我已经更新了我的问题,请看一下。
  • 对不起,我上面说的不正确。让我重新开始:如果宽数据框中的任何单元格具有多个值,那么您将得到您得到的结果。如果有多行具有相同的用户 ID、SAT、GRE、操作和 ConfChall,则会在您的情况下发生这种情况。这不会发生在您的数据样本中,但会发生在您的真实数据中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-25
  • 2018-01-31
  • 2020-09-18
  • 2015-07-18
  • 2013-10-22
相关资源
最近更新 更多