通常情况下,我会使用一个非常基本的从长到宽的重塑,但它似乎正在丢弃我的聚合变量。设置是我有一个机械土耳其人的工作,我一式三份执行---我希望MTurk1,Mturk2,MTurk3的答案是他们自己的数据框中的变量,但我输入的作业字段唯一ID,所以我可以稍后用一个函数将它们相互比较。
当前格式:
> head(mturk)
AssignmentStatus Input.id Input.State Answer.Q1thing
1 Approved 134231 NY Myguess
2 Approved 134231 NY Myguess
3 Approved 134231 NY BadGuess
4 Submitted 134812 CA Another
5 Approved 134812 CA Another
6 Approved 134812 CA Another
我希望这成为
Input.id Input.State Answer.Q1thing.1 Answer.Q1thing.2 Answer.Q1thing.3 AssignmentStatus.1 AssignmentStatus.2 AssignmentStatus.3
134231 NY Myguess Myguess BadGuess Approved Approved Approved
134812 CA Another Another Another Submitted Approved Approved
或理想情况下,如果有一个变量可以在操作中重做列名....
Id State Answer1 Answer2 Answer3 Status1 Status2 Status3
134231 NY Myguess Myguess BadGuess Approved Approved Approved
134812 CA Another Another Another Submitted Approved Approved
dat <- reshape(mturk, timevar="Answer.Q1thing", idvar=c("Input.id", "Input.state"), direction="wide")
这似乎失败了,因为大多数重塑长到宽的函数都期望变宽的变量本身就是一个明确的文本字段---也就是说,这不是一个长到宽的重构操作,因为我不喜欢我不想要一个名为“MyGuess”“BadGuess”和“Another”的变量,但我想要一个包含这些值的通用“Answer.X”变量。我不是试图以任何方式聚合,例如均值或总和,只需在新地点列出值。
所以,这个问题有两个方向:
答案 0 :(得分:3)
如果您的数据位于data.table
,则可以按如下方式进行单行:
library(data.table)
mturk.dt <- as.data.table(mturk)
mturk.dt[, as.list(
rbind(c(Answer.Q1thing, AssignmentStatus))
)
, by=list(Id=Input.id, State=Input.State)]
请注意,by
参数也会处理名称更改!
如果要正确命名其他列,请在事后使用setnames
,或者更动态地使用setattr
参数中的j=..
,如下所示:
## Assuming 'res' is the reshaped data.table form above:
## Change the names of the six V1, V2.. columns
setnames(res, paste0("V", 1:6), c(paste0("Answer", 1:3), paste0("Status", 1:3)))
j=..
## Use `as.data.table` instead of `as.list`, to preserve new names
mturk.dt[, as.data.table(
rbind(c(
setattr(Answer.Q1thing, "names", paste0("Answer", seq(Answer.Q1thing )))
, setattr(AssignmentStatus, "names", paste0("Status", seq(AssignmentStatus)))
))
)
, by=list(Id=Input.id, State=Input.State)]
Id State Answer1 Answer2 Answer3 Status1 Status2 Status3
1: 134231 NY Myguess Myguess BadGuess Approved Approved Approved
2: 134812 CA Myguess Myguess BadGuess Approved Approved Approved
答案 1 :(得分:1)
使用plyr
:
res = ddply(dat,.(Input.id,Input.State),
function(x)unlist(as.character(x$Answer.Q1thing)))
setNames(res,c('Id','State','Answer1','Answer2','Answer3'))
Id State Answer1 Answer2 Answer3
1 134231 NY Myguess Myguess BadGuess
2 134812 CA Another Another Another
编辑
如果您的答案少于3个:
res = ddply(dat,.(Input.id,Input.State),
function(x)
{
xx= unlist(as.character(x$Answer.Q1thing))
if(length(xx)==3)xx
else c(xx,rep(NA,3-length(xx)))
})
答案 2 :(得分:1)
这非常有帮助,@ Ricardo和@agstudy。我意识到我的重塑不起作用只是因为它需要一个独特的,绝对的“时间变量”。我认为在大多数情况下,你确实有一个像这样的分类标签/因子,这很容易,但是计算它们并不难,并将计数变成标签。
我遇到的第二个问题是我的答案数量不一致;你们都为此提供了很好的帮助,但我也能够生成一个计数器然后实现我原来的长到宽。
如果计数<&lt; 3,这是一个Input.id只有2个答案的地方,我为此获得了NA,这就是我想要的。
总而言之:
mturk$idx <- with(mturk, ave(Input.id, Input.id, FUN=seq_along)) # weird!
dat <- reshape(mturk, timevar="idx", idvar=c("Input.id", "Input.state"), direction="wide")
我使用语法对我发现的here组中的序列进行计数。这在使用ave()
函数时有点特殊,但似乎在其他几个答案中出现。试过了rtl
,但没有运气。使用ave(x,x,seq_along)似乎主要是一个避免排序的黑客。将这种解决方法用于组中的序列是很奇怪的,因为很明显count()和rtl()都有效地在temp变量中创建了这个序列。
我喜欢data.table允许这种排序更好的方式。
答案 3 :(得分:0)
From data.table v1.9.5+,dcast
可以处理多个value.var
列,即我们可以同时投放多个列。我们可以简单地做:
dt[, id := seq_len(.N), by=Input.id]
dcast(dt, Input.id + Input.State ~ id,
value.var=c("AssignmentStatus", "Answer.Q1thing"))
# Input.id Input.State 1_AssignmentStatus 2_AssignmentStatus 3_AssignmentStatus
# 1: 134231 NY Approved Approved Approved
# 2: 134812 CA Submitted Approved Approved
# 1_Answer.Q1thing 2_Answer.Q1thing 3_Answer.Q1thing
# 1: Myguess Myguess BadGuess
# 2: Another Another Another
或者一起排成一行:
dcast(dt, Input.id + Input.State ~ dt[, seq_len(.N), by=Input.id]$V1,
value.var=c("AssignmentStatus", "Answer.Q1thing"))