1

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

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 个)以及任何处于中位数(对于该主题)的值,并重新计算中位数(对于该主题)。

4

3 回答 3

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
于 2010-10-15T03:27:40.023 回答
2

继约翰的回答之后,要对每个主题进行中位数,请使用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))

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

于 2010-10-15T10:32:35.937 回答
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。

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

唯一不再起作用的情况是,当您剩下 1 个值时(那时将是中位数,应该将其删除,因此理论上没有结果 - 请参阅 rt1 中的主题 1),或者当所有值相等(在这种情况下,所有值都被删除,并且 - 再次 - 没有结果。)

于 2010-10-15T11:46:54.783 回答