0

我们有一个数据集,第一列中有 ID 号,然后在接下来的 240 列中回答了 240 个问题中的每一个问题。我们想通过找到相同响应的连续或运行长度的最大值和平均值来评估每个主题的响应的有效性。例如,如果受试者回答(1, 1, 1, 2, 2, 5, 5, 5, 5, 1)了 10 个问题,则最大值为 4,平均值为 2.5。

我试图在 R 中使用 解决这个问题rle(),但是在应用rle()到数据帧的每一行之后,我无法提取长度。一旦我提取了长度,我认为应用max()mean(). 任何有关达到这一点的帮助或建议将不胜感激。

还有两个小问题,这里不一定要回答。首先是找到每个响应的最大值和平均值(有五个可能的响应,即 1 到 5)会提供更多信息。在上面的示例中,1、2 和 5 的最大值和均值将分别为 3 和 2、2 和 2、4 和 4。第二个是我不知道如何应用于rle()240 个响应排他性的,即,而不是 ID 号。在操作 R 中的数据框之前,我一直在删除 ID 号列,这很好,但如果我无意中重新排列行会导致错误。

谢谢!

4

2 回答 2

1

rle函数返回一个列表,但这并不是很明显,因为当您键入对象的名称时,可以让 R 打印您想要的任何内容,并且作者rle已使其打印其他内容。为了找出对象的结构,您可以使用str,例如

x <- c(1, 1, 1, 2, 2, 5, 5, 5, 5, 1)
codes <- rle(x)
str(codes)

codes$lengths您可以通过键入相应的值来获取长度。

无论如何,尽管有统计问题,这里是如何做你想做的事。假设你有 30 个科目,他们回答了 8 个问题。您的数据可能如下所示

set.seed(123)
repsonses <- data.frame(matrix(sample(0:5, 8*30, replace=T), nc=8))

> head(responses)
  X1 X2 X3 X4 X5 X6 X7 X8
1  3  2  4  2  4  1  1  5
2  1  5  2  1  5  3  1  1
3  1  3  1  2  3  5  5  3
4  4  4  5  3  4  2  4  2
5  5  5  2  5  3  1  2  4
6  3  3  3  3  1  1  3  2

您可以像这样提取每个主题的最大运行长度:

> max.lengths <- apply(responses, 1, function(x) max(rle(x)$lengths))
> max.lengths
 [1] 2 2 2 2 2 4 3 1 1 2 2 1 2 3 2 1 2 2 1 2 1 2 1 2 2 2 2 2 2 1

前 5 个科目的最大长度为 2,第六个科目的最大长度为 4,所以看起来是正确的。

同样对于平均长度

> mean.lengths <- apply(responses, 1, function(x) mean(rle(x)$lengths))
> head(mean.lengths)
[1] 1.142857 1.142857 1.142857 1.142857 1.142857 2.000000

例如,第一个人的平均长度是 $1,1,1,1,1,2,1$ 的平均值,即 $8/7$,这与 R 所说的一致。

要通过响应分解整个事情,您可以使用相同的想法和这样的tapply功能:

bd <- function(x){
    means <- tapply(x$lengths, factor(x$values,levels=0:5), mean)
    means[is.na(means)] <- 0
    maxes <- tapply(x$lengths, factor(x$values,levels=0:5), max)
    maxes[is.na(maxes)] <- 0
    M <- rbind(means, maxes)
    rownames(M) <- c("mean", "max")
    M
}

lapply(apply(responses, 1, rle), bd)

这会输出另一个列表。例如,如果你向上滚动,你会看到主题 25,它说

[[25]]
     0 1 2 3 4 5
mean 0 1 2 1 0 2
max  0 1 2 1 0 2

与之比较

> responses[25,]
   X1 X2 X3 X4 X5 X6 X7 X8
25  3  5  5  3  2  2  1  3

所以它给出了正确的答案。您可以为此列表命名,例如

break.downs <- lapply(apply(responses, 1, rle), bd)

然后您可以i通过键入访问主题条目

break.downs[[i]]

对于 ID 号列的问题,如果包括在内,例如第 1 列,您可以对它进行整个分析responses[ ,-1],这应该没问题。$-1$ 只是删除第一列。

PS。抱歉,我刚刚注意到我是用 $0$ 到 $5$ 而不是 $1$ 到 $5$ 来做的,但你只需要在函数中更改levels=0:5为,它应该也能正常工作。levels=1:5bd

于 2013-06-05T04:37:57.817 回答
0

我偏爱这个data.table包裹。要使用它,首先要重塑为长格式。然后使用rle(确保获取结果的第一个列表元素,使用[[1]]),获取最大值/平均值,并按受访者 ID 分组。

这是一个包含 5 个受访者和 10 个问题的示例:

library(data.table)
set.seed(8028)

responses <- data.frame(cbind(id=1:5,matrix(sample(1:5, 10*5, replace=T), nc=10)))
responses
#   id V2 V3 V4 V5 V6 V7 V8 V9 V10 V11
# 1  1  3  4  2  5  1  2  4  4   1   3
# 2  2  2  2  4  5  5  2  3  3   3   1
# 3  3  5  1  3  3  4  4  1  4   2   2
# 4  4  3  2  4  5  2  2  1  4   1   3
# 5  5  5  2  4  5  3  1  4  1   2   4

responses.long<-data.table(reshape(responses, idvar="id", varying=list(2:11), direction="long"),key=c("id","time"))

responses.long[,list(run=max(rle(V2)[[1]]), mean=mean(rle(V2)[[1]])), by="id"]
#    id run     mean
# 1:  1   2 1.111111
# 2:  2   3 1.666667
# 3:  3   2 1.428571
# 4:  4   2 1.111111
# 5:  5   1 1.000000

这个问题不是更适合 StackOverflow 吗?

于 2013-06-05T06:06:14.970 回答