请原谅我对R世界的新任务,请提前感谢您的帮助。
我想分析实验数据。
数据以长格式显示,需要重新调整为宽,但我无法确切知道如何做到这一点。大多数熔化/铸造和重塑的例子都涉及更简单的数据帧。
每当受试者回答关于实验的问题时,他的用户ID,位置,年龄和性别被记录在一行中,然后他的一系列问题的实验数据被输入这些变量旁边。在这里,他们可以回答关于实验的任何问题,他们可能会回答不同的项目(这很复杂,但必须是这样)。
原始数据如下所示:
User_id, location, age, gender, Item, Resp
1, CA, 22, M, A, 1
1, CA, 22, M, B, -1
1, CA, 22, M, C, -1
1, CA, 22, M, D, 1
1, CA, 22, M, E,-1
2, MD, 27, F, A, -1
2, MD, 27, F, B, 1
2, MD, 27, F, C, 1
2, MD, 27, F, E, 1
2, MD, 27, F, G, -1
2, MD, 27, F, H, -1
我想重塑这些数据,让每个用户都在一行,看起来像这样:
User_id, location, age, gender, A, B, C, D, E, F, G, H
1, CA, 22, M, 1, -1, -1, 1, -1, 0, 0, 0,
2, MD, 27, F, -1, 1, 1, 1, 0, 1, -1, -1
我认为这只是找到正确的重塑方程式的问题,但我已经使用了几个小时,而且我不能完全得到我想要的东西,因为大多数例子中没有重复的人口统计数据,因此可以更简单地旋转。如果我忽略了一些简单的事情,我感到非常抱歉。
答案 0 :(得分:11)
使用data.table
即可:
library(data.table)
> dcast(dt, User_id + location + age ~ Item, value.var = "Resp", fill = 0L)
User_id location age A B C D E G H
1: 1 CA 22 1 -1 -1 1 -1 0 0
2: 2 MD 27 -1 1 1 0 1 -1 -1
答案 1 :(得分:10)
有一个名为tidyr的软件包可以更轻松地融化和重塑数据框架。在您的情况下,您可以直接使用tidyr::spread
:
result = spread(df, Item, Resp)
然而,这将使用NA
填充缺少的条目:
User_id location age gender A B C D E G H
1 1 CA 22 M 1 -1 -1 1 -1 NA NA
2 2 MD 27 F -1 1 1 NA 1 -1 -1
您可以通过替换它们来解决此问题:
result[is.na(result)] = 0
result
# User_id location age gender A B C D E G H
# 1 1 CA 22 M 1 -1 -1 1 -1 0 0
# 2 2 MD 27 F -1 1 1 0 1 -1 -1
...或使用fill
参数:
result = spread(df, Item, Resp, fill = 0)
为了完整起见,反之亦然(即复制原始data.frame
)通过gather
(通常称为“融化”)起作用:
gather(result, Item, Resp, A : H)
- 这里的最后一个参数告诉gather
要收集哪些列(并且它支持简洁的范围语法)。
答案 2 :(得分:10)
这里总是优雅的stats::reshape
版本
(newdf <- reshape(df, direction = "wide", timevar = "Item", idvar = names(df)[1:4]))
# User_id location age gender Resp. A Resp. B Resp. C Resp. D Resp. E Resp. G Resp. H
# 1 1 CA 22 M 1 -1 -1 1 -1 NA NA
# 6 2 MD 27 F -1 1 1 NA 1 -1 -1
NA
中的reshape()
缺少值,而且名称不是我们想要的。所以我们需要做更多的工作。在这里,我们可以更改名称,并将NA
s替换为同一行中的零,以达到您想要的结果。
replace(setNames(newdf, sub(".* ", "", names(newdf))), is.na(newdf), 0)
# User_id location age gender A B C D E G H
# 1 1 CA 22 M 1 -1 -1 1 -1 0 0
# 6 2 MD 27 F -1 1 1 0 1 -1 -1
当然,如果我们把它分成两个单独的行,那么代码肯定会更清晰。另请注意,原始数据中的F
中没有Item
,因此与您的输出存在差异。
数据:强>
df <- structure(list(User_id = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L,
2L, 2L), location = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L,
2L, 2L, 2L), .Label = c(" CA", " MD"), class = "factor"), age = c(22L,
22L, 22L, 22L, 22L, 27L, 27L, 27L, 27L, 27L, 27L), gender = structure(c(2L,
2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c(" F", " M"
), class = "factor"), Item = structure(c(1L, 2L, 3L, 4L, 5L,
1L, 2L, 3L, 5L, 6L, 7L), .Label = c(" A", " B", " C", " D", " E",
" G", " H"), class = "factor"), Resp = c(1, -1, -1, 1, -1, -1,
1, 1, 1, -1, -1)), .Names = c("User_id", "location", "age", "gender",
"Item", "Resp"), class = "data.frame", row.names = c(NA, -11L
))