重塑数据从长格式到宽格式 - 理解重塑参数

3

我有一个长格式的数据框dogs,我正在尝试使用reshape()函数将其重新格式化为宽格式。它当前的样子是这样的:

dogid  month  year  trainingtype  home  school  timeincomp
12345  1      2014  1             1     1       340
12345  2      2014  1             1     1       360
31323  12     2015  2             7     3       440
31323  1      2014  1             7     3       500
31323  2      2014  1             7     3       520

dogid列是一组ID,每只狗都有一个。月份列的取值范围是1到12,涵盖了12个月, 年份从2014年到2015年。Trainingtype的取值范围是1到2。每只狗在每个月-年-Trainingtype组合中都有一个timeincomp值, 因此每只狗有48个条目。Home和School的取值范围是1-8,在每个狗的记录中都是常量(相同狗的所有条目具有相同的school和home值)。Time in comp 是响应变量。

我希望我的表格看起来像这样:

dogid  home  school  month1year2014trainingtype1  month2year2014trainingtype1
12345  1     1       340                          360
31323  7     3       500                          520

等等(每个月-年-培训类型组合的列)

我应该在reshape中使用哪些参数才能实现这一点?

4个回答

5
你可以使用reshape2包中的函数dcast。它更易于理解。公式的左侧是保持不变的部分,而右侧则是需要转换为宽格式的部分。
当有多个数字与一个案例相关联时,我们可以使用fun.aggregate函数来应用计算方法。如果你确定没有重复的案例,可以使用meansum函数。
dcast(data, formula= dogid + home + school ~ month + year + trainingtype,
value.var = 'timeincomp',
fun.aggregate = sum)

希望这能起作用:

  dogid home school 1_2014_1 2_2014_1 12_2015_2
1 12345    1      1      340      360         0
2 31323    7      3      500      520       440

5
在这种情况下,使用基本的reshape,您实际上想要一个涉及三个时间变量的interaction()来定义您的宽变量,因此:
idvars  <- c("dogid","home","school")
grpvars <- c("year","month","trainingtype")
outvar  <- "timeincomp"
time    <- interaction(dat[grpvars])

reshape(
  cbind(dat[c(idvars,outvar)],time),
  idvar=idvars,
  timevar="time",
  direction="wide"
)

#  dogid home school timeincomp.2014.1.1 timeincomp.2014.2.1 timeincomp.2015.12.2
#1 12345    1      1                 340                 360                   NA
#3 31323    7      3                 500                 520                  440

3

您可以使用tidyr这个新替代品来完成与reshape2相同的操作:

library(tidyr)
library(dplyr)
data %>% unite(newcol, c(year, month, trainingtype)) %>%
         spread(newcol, timeincomp)

  dogid home school 2014_1_1 2014_2_1 2015_12_2
1 12345    1      1      340      360        NA
2 31323    7      3      500      520       440

首先,我们将年份、月份和培训类型三列合并为一个名为newcol的新列,然后使用timeincomp作为值变量展开数据。在spread函数中,填充值为NA是因为我们没有值,您可以通过将fill = NA更改为其他值来进行填充。

我还不太习惯使用tidyr,一直在尝试将gather()与spread()结合起来,但没有意识到'unite()是必要的!谢谢! - eivicent

1

在tidyr_1.0.0及以上版本中,另一个选项是pivot_wider

library(tidyverse)

df <- tribble(
~dogid, ~month, ~year, ~trainingtype, ~home, ~school, ~timeincomp,
12345,  1,  2014, 1, 1, 1, 340,
12345,  2,  2014, 1, 1, 1, 360,
31323,  12, 2015, 2, 7, 3, 440,
31323,  1,  2014, 1, 7, 3, 500,
31323,  2,  2014, 1, 7, 3, 520
)


df %>% pivot_wider(
  id_cols = c(dogid,home, school),
  names_from = c(month, year, trainingtype),
  values_from = c(timeincomp),
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接