Нахождение матрицы строки медиана и абсолютное отклонение - PullRequest
2 голосов
/ 27 мая 2011

У меня есть фрейм данных с 22239 строками и 200 столбцами. Первый столбец - NAME - это символ, а остальные столбцы - числовые. Моя цель - оперировать всеми элементами строк:

  • Нахождение медианы строк;
  • Вычитание медианы из элемента строки (значение);
  • Нахождение среднего абсолютного отклонения строк (безумный);
  • Разделение элементов строк на строки mad.

Я пробовал таким образом

edata <- read.delim("a.txt", header=TRUE, sep="\t")

## Converting dataframe into Matrix
## Taking all rows but starting from 2 column to 200
data <- as.matrix(edata[,2:200]) 
for(i in 1:22239){  #rows below columns
    for(j in 1:200) {
        m <- median(data[i,]) # median of rows
        md <- mad(normdata[i,]) # mad of rows
        a <- data[i,j]  # assigning matrix element value to a
        subs = a-m    # substracting
        escore <- subs/md  # final score
        data[i,j] <- escore  # assigning final score to row elements

После получения новых значений для каждого элемента строк я хочу отсортировать его по 75% квантилям на основе столбца NAME. Но я не уверен, как это сделать.

Я знаю, что мой код недостаточно эффективен для памяти. Когда я запускаю приведенный выше код, цикл очень медленный. Пробовал foreach, но не смог. Ребята, можете ли вы предложить мне хороший способ решения подобных проблем?

Ответы [ 5 ]

3 голосов
/ 27 мая 2011

Это идеальная работа для sweep().

set.seed(47)
dat <- matrix(rnorm(22239 * 200), ncol = 200)
rmeds <- apply(dat, 1, median)     ## row medians
rmads <- apply(dat, 1, mad)        ## row mads
dat2 <- sweep(dat, 1, rmeds, "-")  ## sweep out the medians
dat2 <- sweep(dat2, 1, rmads, "/") ## sweep out the mads

. Это можно немного ускорить, если не использовать mad(), так как он снова вычисляет медианы:

rmeds <- apply(dat, 1, median)     ## row medians
dat3 <- sweep(dat, 1, rmeds, "-")  ## sweep out the medians
rmads <- 1.4826 * apply(abs(dat3), 1, median)        ## row mads
dat3 <- sweep(dat3, 1, rmads, "/") ## sweep out the mads

R> all.equal(dat2, dat3)
[1] TRUE

Обратите внимание, что R * mad() умножается на константу 1,4826 для достижения асимптотически нормальной согласованности, следовательно, дополнительный бит во втором примере.

Некоторые временные параметры в моей системе:

## first version
   user  system elapsed 
  6.215   0.183   6.412 

## second version
   user  system elapsed 
  4.365   0.167   4.535 

Для @Ответ Ника, который я получаю:

## @Nick's Version
   user  system elapsed 
  5.900   0.032   5.955

, что последовательно быстрее, чем моя первая версия, но немного медленнее, чем вторая версия, опять же, потому что медианы вычисляются дважды.

2 голосов
/ 27 мая 2011

Как насчет этого: (Я создал другую матрицу для начала, но метод тот же)

dta<-matrix(rnorm(200), nrow=20)
dta.perrow<-apply(dta, 1, function(currow){c(med=median(currow), mad=mad(currow))})
result<-(dta - dta.perrow[1,])/dta.perrow[2,]

Я уверен, что есть еще лучшие способы, но HTH.

1 голос
/ 28 мая 2011

Вы можете включить все шаги в функцию и использовать только один цикл применения.

rfun <- function(x) {
         me<- median(x)
         md<-mad(x,center=me,constant=1)
         return((x-me)/md)}

dat_s <- apply(dat,1,rfun)
1 голос
/ 27 мая 2011

У вас есть специальные функции для работы с данными строк, но я люблю использовать apply.Вы можете думать о применении как о цикле for (который, по сути, работает), работающем со строкой одновременно.

my.m <- matrix(runif(100), ncol = 5)
my.median <- apply(X = my.m, MARGIN = 1, FUN = median) #1
my.m - my.median #2
my.mad <- apply(X = my.m, MARGIN = 1, FUN = mad) #3
my.m/my.mad #4
1 голос
/ 27 мая 2011

R, как и Matlab, оптимизирован для векторных операций. Ваши циклы for, вероятно, самый медленный способ достижения этого. Медианы каждой строки могут быть рассчитаны с использованием функции apply, а не цикла for. Это даст вам вектор столбцов медиан. например,

apply(edata,1,median)

Аналогичные подходы могут быть использованы для других мер. Помните, что избегание циклов for в R / matlab, как правило, ускоряет ваш код.

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