2

重複の可能性:
R でループが遅いのはなぜですか?

次のタスクを検討してください。データセットには、20,000 人の「ユーザー」に対して 40 の変数があります。各ユーザーには、1 ~ 150 の観測値があります。すべてのユーザーは、データと呼ばれるマトリックスに積み上げられます。最初の列はユーザ​​ーの ID で、ユーザーを識別します。すべての ID は、userid と呼ばれる 20,000 X 1 のマトリックスに格納されます。

次のRコードを検討してください

useridl = length(userid)
itime=proc.time()[3]    
for (i in 1:useridl) {
temp =data[data[,1]==userid[i],]
   }
 etime=proc.time()[3]
 etime-itime

このコードは 20,000 人のユーザーを処理し、毎回一時マトリックスを作成します。userid[i] に属する観測のサブセット。MacPro で約 6 分かかります。

MatLab では、同じタスク

tic
for i=1:useridl
temp=data(data(:,1)==userid(i),:);
end
toc

1分かかります。

なぜRはとても遅いのですか? これは標準的なタスクです。どちらの場合も行列を使用しています。何か案は?

4

1 に答える 1

6

@joranがコメントしたように、それは悪いRプラクティスです。lapply元のマトリックスを繰り返しサブセット化する代わりに、サブセットを1回リストに入れてから、または同様のリストを繰り返し処理します。

# make example data
set.seed(21)
userid <- 1:1e4
obs <- sample(150, length(userid), TRUE)
users <- rep(userid, obs)
Data <- cbind(users,matrix(rnorm(40*sum(obs)),sum(obs),40))

# reorder so Data isn't sorted by userid
Data <- Data[order(Data[,2]),]
# note that you have to call the data.frame method explicitly,
# the default method returns a vector
system.time(temp <- split.data.frame(Data, Data[,1])) ## Returns times in seconds
#    user  system elapsed 
#    2.84    0.08    2.92 

私の推測では、tempオブジェクトを継続的に上書きしているため、ガベージコレクターによってRコードの速度が低下していると思います。

于 2012-10-30T16:04:57.767 に答える