我的数据框有22239行& 200列。第一列 - NAME
- 是一个字符,其他列是数字。我的目标是通过以下方式对行的所有元素进行操作:
我试过这种方式
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
,但无法成功。你们能告诉我处理这类问题的好方法吗?
答案 0 :(得分:3)
这是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的回答我得到了:
## @Nick's Version
user system elapsed
5.900 0.032 5.955
一直比我的第一个版本快,但比第二个版本慢一点,因为中位数被计算两次。
答案 1 :(得分:2)
这个怎么样: (我创建了另一个矩阵,但方法是相同的)
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。
答案 2 :(得分:1)
R与matlab一样,针对矢量运算进行了优化。你的for循环可能是实现这一目标的最慢方法。可以使用apply函数计算每行的中位数,而不是for循环。这将为您提供中位数的列向量。 e.g。
apply(edata,1,median)
类似的方法可用于其他措施。请记住,避免使用R / matlab中的for循环通常会加快代码的速度。
答案 3 :(得分:1)
您有处理行数据的特殊功能,但我喜欢使用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
答案 4 :(得分:1)
您可以将所有步骤放入功能并仅使用一个应用循环。
rfun <- function(x) {
me<- median(x)
md<-mad(x,center=me,constant=1)
return((x-me)/md)}
dat_s <- apply(dat,1,rfun)