重新整形R而不进行聚合(例如MTurk响应字符串)

时间:2014-02-06 18:27:39

标签: r reshape mechanicalturk

通常情况下,我会使用一个非常基本的从长到宽的重塑,但它似乎正在丢弃我的聚合变量。设置是我有一个机械土耳其人的工作,我一式三份执行---我希望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”变量。我不是试图以任何方式聚合,例如均值或总和,只需在新地点列出值。

所以,这个问题有两个方向:

  1. 这种操作有其他名称吗?这是展开的,未展开的,未展开的吗?
  2. 如何在R?
  3. 中执行此操作

4 个答案:

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