通过关系更新计算每个受试者的中位数?

时间:2010-10-14 22:19:47

标签: r if-statement median

我的数据看起来像这样(这是用于说明的测试数据):

test <- matrix(c(1, 1, 1, 2, 2, 2 , 529, 528, 528, 495, 525, 510,557, 535, 313,502,474, 487 ), nr=6, dimnames=list(c(1,2,3,4,5,6),c("subject", "rt1", "rt2")))

我需要把它变成这个:

test2<-matrix(c(1,1,1,2,2,2,529,528,528,495,525,510,"slow","slow","fast","fast","slow","slow",557, 535, 313,502,474, 487,"fast","fast","slow","slow","fast","fast"), nr=6, dimnames=list(c(1,2,3,4,5,6),c("subject", "rt1","speed1", "rt2","speed2")))

因此计算speed1列:计算受试者的中位数rt1。如果单个值小于中值,则快速得分。如果rt1的单个细胞值大于中位数,则得分变慢。如果细胞值处于中位数,则从分析中删除细胞(删除或NA),并重新计算该受试者的中位数。对于speed2列重复此过程,但使用rt2。

也许某种if语句?

澄清:我希望每个受试者的中位数(总共有40个)和中位数(对于该受试者)的任何值被排除,并且重新计算中位数(对于该主题)。

3 个答案:

答案 0 :(得分:4)

编辑实际上是主题媒体

在实际情况下,您可能使用的是数据框,因此您在矩阵中往往很重要。所以,让我们首先解决这个问题。矩阵要求您使用单一类型的数据。我不认为你真的希望你的数字是文本。您的其他变量不能是数字。因此,test2应该以......开头。

test2 <- data.frame(test)

可能

test2$subject <- factor(test2$subject)

你可能想要添加一个实际上是中位数/主题的列,只是为了检查你正在做的是正确的。从这里开始,我将使用RT1,您可以复制RT2。

test2$rt1med <- ave(test2$rt1, test2$subject, FUN = median)

这将生成一个列,其中包含存储在其中的每个主题的中位数。如果你愿意,你可能没有把它作为一个列而是一个独立的向量。现在,你是对的,它就像一个if语句一样简单,ifelse()语句是准确的。

test2$speed1 <- ifelse(test2$rt1 > test2$rt1med, 'slow', 'fast')

我把中间人留在了框架中。你说你想让他们走了好的,只需将框架设置为自己而没有中位数......

test2 <- test2[test2$rt1 != test2$rt1med,]

但实际上,最好通过指示它们来跟踪实际的中值,也许用NA ...

test2$rt1[test2$rt1 == test2$rt1med] <- NA

答案 1 :(得分:2)

继John的回答之后,要按照主题中位数做,请使用tapply

test2 <- data.frame(test)
test2$subject <- factor(test2$subject)
test3 <- data.frame(subject=levels(test2$subject),median.rt1=tapply(test2$rt1,test2$subject,median),median.rt2=tapply(test2$rt2,test2$subject,median))
test2 <- merge(test2,test3)
test2$speed1 <- ifelse(test2$rt1 < test2$median.rt1, 'fast', 'slow') 
test2$speed2 <- ifelse(test2$rt2 < test2$median.rt2, 'fast', 'slow')

要删除您可以使用的中位数值,

subset(test2,!(rt1==median.rt1 | rt2==median.rt2))

或者,如果您期望数值表示错误导致直接相等测试出现问题,则可以使用一些基于容差的测试。然后,您可以再次运行tapplymerge行(尽管可能将原始中间列分组)以计算新的中位数,并根据需要重新设置速度分类。就个人而言,我会使用嵌套的ifelse来分类为快,慢或平均。

答案 2 :(得分:2)

考虑到中位数“重新计算”的另一种解决方案:

test2 <- data.frame(test)

makespeed <- function(x){
    id <- x != median(x)
    ifelse(x[id]-median(x[id]) <0,"slow","fast")
}

tapply(test2$rt1,as.factor(test2$subject),makespeed)

现在想一想。您有三种选择:

  1. 你有很多案件, 中位数定义为 两个中间病例的平均值。如果 这两者并不相等 彼此,然后没有价值等于 中位数。

  2. 你的案件数量奇怪,所以 中位数等于1的值 数据。如果删除那个, 你有很多案件和 你回到了案例1。

  3. 您有一系列等于中位数的值。你将得到偶数个案例,其中两个中间案例不同。一个低于先前计算的中位数,一个更高。所以你回到了案例1。

  4. 所以事实上,如果你真的对中位数的差异感兴趣,你可以使用我的代码。如果您只想知道它是快还是慢,那么您甚至不必重新计算中位数。删除必要值后,高于/低于旧中位数的案例仍将高于/低于新的中位数。所以基本上,尽管詹姆斯和约翰的代码在技术上并没有按照你的要求做,但它并没有什么区别。事实上,它可以让以后更容易重建数据帧。

    只有这种情况不再起作用的情况是,当你剩下1个值时(那将是中位数,并且应该被移除所以理论上没有结果 - 参见rt1中的主题1),或者当所有值都相等时(在这种情况下,所有值都被删除并且-again-没有结果。)