问题描述
|
我有一个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,mad) ## row mads
dat2 <- sweep(dat,rmeds,\"-\") ## sweep out the medians
dat2 <- sweep(dat2,rmads,\"/\") ## sweep out the mads
不使用ѭ5可以加快速度,因为它会再次计算中位数:
rmeds <- apply(dat,median) ## row medians
dat3 <- sweep(dat,\"-\") ## sweep out the medians
rmads <- 1.4826 * apply(abs(dat3),median) ## row mads
dat3 <- sweep(dat3,\"/\") ## 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,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,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,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,rfun)