R:从长转宽并聚合具有匹配 ID 的行

R: Transposing from long to wide and aggregating rows with matching ID

这是我已经研究了一段时间的东西,只是制作单独的数据框并做 full_join,但我认为有更简单的方法。

总的来说,我想从长格式数据框中按类型计算个人 ID 从时间 1 到时间 2 的值之间的差异。这是我认为我可以做到的方法之一,但如果其他人有其他技术或想法,我也想听听他们的意见。

但是,我也想知道如何解决这个移调问题,因为我很好奇。

这是我的问题。

我有一个长格式的数据框,其中包含针对两个不同时间段的 5 种不同度量。我想将此数据框从长格式转换为宽格式,这样 DF 就不会像这样(注意,并非所有类型都包括在内——为了长度只做了 2 个):

(示例 df1)

ID   Time  Value  Type
1     1      7     Type1
1     2      8     Type1
2     1      9     Type1
2     2      10    Type1
1     1      13    Type2
1     2      15    Type2
2     1      17    Type2
2     2      19    Type2

我希望它看起来更像这样:

(示例 df 2)

ID   Type1.1   Type1.2    Type2.1  Type2.2
1      7          8          13      15
2      9          10         17      19 

我使用:

library(dplyr)
library(tidyr)
df.new <- df %>%
spread(Type, Measurement.Value)

并从正确轨道上的示例 df 1 中获取:

(示例 df 3)

ID    Time    Type1    Type2
1       1       7        13
1       2       8        15
2       1       9        17
2       2       10       19

但是现在我想把每个类型的时间都分散开来。当我在示例 df3:

上做这样的事情时
newer.df <- df.new %>%
spread(Time, Type1)

做这个:

ID   Type1.1   Type1.2
1      7          NA 
1      NA         8 
2      9          NA
2      NA         10

所以,它为每一行生成一个 NA -- 有没有办法可以通过 ID 将行折叠到彼此?我想我错过了什么。

请记住,在我的示例代码中,我只使用了 2 种类型,但实际上我有 5 种类型——只是想提供简化的代码。

我们可以使用 reshape2 包中的 dcast()

library(reshape2)
dcast(df, ID ~ Type + Time, value.var = "Value")
#  ID Type1_1 Type1_2 Type2_1 Type2_2
#1  1       7       8      13      15
#2  2       9      10      17      19

或者使用原始的 tidyr 包,我们可以这样做:

library(tidyr)
df$Type <- paste(df$Type, df$Time, sep="_")
df$Time <- NULL
spread(df, key=Type, value=Value)
 ID Type1_1 Type1_2 Type2_1 Type2_2
  1       7       8      13      15
  2       9      10      17      19

取消时间列对我有用。似乎 spread 将所有未使用的列视为 dcast 将调用的 id.vars。不过,使用 tidyr 可能会有更优雅的解决方案。