相同响应的条纹/运行的最大和平均长度

时间:2013-06-04 20:46:32

标签: r

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

我尝试使用rle()在R中解决此问题,但在将rle()应用于数据框的每一行后,我无法提取长度。一旦我提取了长度,我认为应用max()mean()相对容易。任何有关达到这一点的帮助或建议都将不胜感激。

还有两个较小的问题,不一定需要在这里回答。首先,找到每个响应的最大值和平均值会更加丰富(有五种可能的响应,即1到5)。在上面的例子中,1,2和5的最大值和均值分别为3和2,2和2,以及4和4.第二个是我不知道如何应用{{1}仅对240个响应,即也不是ID号。在操作R中的数据帧之前,我一直在删除ID号列,这很好,但是如果我无意中重新排列行将导致错误。

谢谢!

2 个答案:

答案 0 :(得分:1)

rle函数返回一个列表,但这并不是很明显,因为在键入对象名称并且rle的作者已经制作时,可以使R打印任意内容它打印别的东西。为了找出对象的结构,您可以使用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:5更改为bd并且它应该也能正常工作。

答案 1 :(得分:0)

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

以下是五个受访者和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吗?