Рассчитать медиану для каждого предмета с обновлением на связи? - PullRequest
1 голос
/ 15 октября 2010

У меня есть данные, которые выглядят так (это тестовые данные для иллюстрации):

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 ]

4 голосов
/ 15 октября 2010

РЕДАКТИРУЕТСЯ, ЧТОБЫ ДЕЙСТВИТЕЛЬНО ПРЕДСТАВЛЯТЬ СУБЪЕКТЫ

Вы склонны разбираться в матрице в примерах, когда на самом деле вы, скорее всего, используете фреймы данных. Итак, давайте сначала уберем это с пути. Матрица требует, чтобы вы использовали один тип данных. У меня не складывается впечатление, что вы действительно хотите, чтобы ваши цифры были текстовыми. Ваши другие переменные не могут быть числами. Следовательно, 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
2 голосов
/ 15 октября 2010

Другое решение, которое учитывает «пересчет» медианы:

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.

Так что, на самом деле, если вы действительно заинтересованы в разнице с медианой, вы можете использовать мой код. Если вы хотите знать только, быстро это или медленно, вам даже не нужно пересчитывать медиану. После удаления необходимых значений случаи, которые были выше / ниже, чем старая медиана, все равно будут выше / ниже, чем новая медиана. В общем, хотя код Джеймса и Джона технически не выполняет то, что вы просили, это не имеет значения. На самом деле, это облегчает восстановление кадра данных впоследствии.

Единственный случай, когда это больше не работает, когда у вас осталось 1 значение (тогда это будет медиана, и его следует удалить, так что теоретически результата нет - см. Тему 1 в rt1), или когда все значения равны (в этом случае все значения удаляются и -again- результата нет.)

2 голосов
/ 15 октября 2010

Исходя из ответа Джона, чтобы сделать медианы по каждому предмету, используйте 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, чтобы классифицировать его как быстрый, медленный или средний.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...