求矩阵行中位数和绝对偏差

| 我有一个22239行和200列的数据框。第一列“ѭ0”是一个字符,其他列是数字。我的目标是通过以下方式对行的所有元素进行操作: 查找行的中位数; 从行元素(值)中减去中位数; 查找各行的中位数绝对偏差(疯狂); 疯狂地将行元素除以行。 我这样尝试
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
在为行的每个元素获取新值之后,我想根据NAME列根据75%的分位数对它进行排序。但是,我不确定该怎么做。 我知道我的代码不是高效的内存。当我运行上面的代码时,循环非常慢。尝试了
foreach
,但未能成功。你们能建议我解决此类问题的好方法吗?     
已邀请:
        这对于
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
不使用ѭ5可以加快速度,因为它会再次计算中位数:
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 \的a5 a乘以常数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 Answer,我得到:
## @Nick\'s Version
   user  system elapsed 
  5.900   0.032   5.955
始终比我的第一个版本快,但比第二个版本慢,这再次是因为中值被计算了两次。     
        这个怎么样: (我创建了另一个矩阵作为起点,但是方法是相同的)
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。     
        像matlab一样,R已针对向量运算进行了优化。您的for循环可能是实现此目标的最慢方法。可以使用apply函数而不是for循环来计算每行的中值。这将为您提供中值的列向量。例如
apply(edata,1,median)
类似的方法可以用于其他措施。请记住,在R / matlab中避免for循环通常会加快代码的速度。     
        您具有处理行数据的特殊功能,但是我喜欢使用apply。您可以将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
    
        您可以将所有步骤置于函数中,并且仅使用一个Apply循环。
rfun <- function(x) {
         me<- median(x)
         md<-mad(x,center=me,constant=1)
         return((x-me)/md)}

dat_s <- apply(dat,1,rfun)
    

要回复问题请先登录注册