我的数据看起来像这样(这是用于说明的测试数据):
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个)和中位数(对于该受试者)的任何值被排除,并且重新计算中位数(对于该主题)。
答案 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))
或者,如果您期望数值表示错误导致直接相等测试出现问题,则可以使用一些基于容差的测试。然后,您可以再次运行tapply
和merge
行(尽管可能将原始中间列分组)以计算新的中位数,并根据需要重新设置速度分类。就个人而言,我会使用嵌套的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的值 数据。如果删除那个, 你有很多案件和 你回到了案例1。
您有一系列等于中位数的值。你将得到偶数个案例,其中两个中间案例不同。一个低于先前计算的中位数,一个更高。所以你回到了案例1。
所以事实上,如果你真的对中位数的差异感兴趣,你可以使用我的代码。如果您只想知道它是快还是慢,那么您甚至不必重新计算中位数。删除必要值后,高于/低于旧中位数的案例仍将高于/低于新的中位数。所以基本上,尽管詹姆斯和约翰的代码在技术上并没有按照你的要求做,但它并没有什么区别。事实上,它可以让以后更容易重建数据帧。
只有这种情况不再起作用的情况是,当你剩下1个值时(那将是中位数,并且应该被移除所以理论上没有结果 - 参见rt1中的主题1),或者当所有值都相等时(在这种情况下,所有值都被删除并且-again-没有结果。)