5

I want to perform calculations for each company number in the column PERMNO of my data frame, the summary of which can be seen here:

> summary(companydataRETS)
     PERMNO           RET           
 Min.   :10000   Min.   :-0.971698  
 1st Qu.:32716   1st Qu.:-0.011905  
 Median :61735   Median : 0.000000  
 Mean   :56788   Mean   : 0.000799  
 3rd Qu.:80280   3rd Qu.: 0.010989  
 Max.   :93436   Max.   :19.000000  

My solution so far was to create a variable with all possible company numbers

compns <- companydataRETS[!duplicated(companydataRETS[,"PERMNO"]),"PERMNO"]

And then use a foreach loop using parallel computing which calls my function get.rho() which in turn perform the desired calculations

rhos <- foreach (i=1:length(compns), .combine=rbind) %dopar% 
      get.rho(subset(companydataRETS[,"RET"],companydataRETS$PERMNO == compns[i]))

I tested it for a subset of my data and it all works. The problem is that I have 72 million observations, and even after leaving the computer working overnight, it still didn't finish.

I am new in R, so I imagine my code structure can be improved upon and there is a better (quicker, less computationally intensive) way to perform this same task (perhaps using apply or with, both of which I don't understand). Any suggestions?

4

2 に答える 2

4

ジョランの勧めで図書館を覗いてみたdata.table。コードの変更点は、

library(data.table) 
companydataRETS <- data.table(companydataRETS)
setkey(companydataRETS,PERMNO)

rhos <- foreach (i=1:length(compns), .combine=rbind) %do% 
      get.rho(companydataRETS[J(compns[i])]$RET)

データセット内の 28659 社のうち 30 社のみで構成された変数を使用して、最初に持っていたコードを ( を使用してsubset) 実行し、一度 を使用してコードを実行しました。2 つのバージョンの出力は次のとおりです。data.tablecompnssystem.time()

使用subset:

ユーザー........ システム.....経過
43.925 ... 12.413...... 56.337

使用するdata.table

ユーザー....... システム..... 経過
0.229..... 0.047....... 0.276

(何らかの理由で、元のコードの%do%代わりにfor を使用すると、より速く実行されました。この場合、 forは を使用するものであり、2 つのうち高速です。)%dopar%system.time()subset%do%

元のコードを一晩実行したままにし、5 時間経っても終了しなかったため、あきらめて終了させました。この小さな変更により、5 分もかからずに結果が得られました (約 3 分だと思います)。

編集

data.tableを使用せずにを使用するさらに簡単な方法がありますforeach。これには、上記のコードの最後の行を

rhos <- companydataRETS[ , get.rho(RET), by=PERMNO]
于 2012-06-26T21:11:08.247 に答える
0

このようなことを行うには多くの方法があり、あなたのforeachソリューションはその1つです。あなたが提供したコードを見るだけで、最も適切な解決策しか推測できません...

ただし、コードの最大の速度低下は、実際にget.rhoはループやサブセット化ではなく関数であると思います。その機能を共有したい場合は、物事をスピードアップし、いくつかの「R-イズム」を明確にする驚くべき答えが得られるに違いありません.

そうは言っても、あなたがしていることに代わる多くの選択肢もあります。

このplyrパッケージは、このタイプの計算に合わせて作られています。分割適用結合戦略を使用します。関数の最初の 2 文字は、入力と出力のデータ型を示します。

data.frame を入力して data.frame を出力しているので、ddply使用する関数は次のとおりです。

library(plyr)
ddply(companydataRETS, .(PERMNO), summarise, get.rho(RET))

Windows 以外を使用している場合は、この calc を使用して簡単にマルチスレッド化できます。

library(doMC)
registerDoMC()
ddply(companydataRETS, .(PERMNO), summarise, get.rho(RET), .parallel=TRUE)

tapplyも完璧な候補です。

tapply(companydataRETS$RET, companydataRET$PERMNO, get.rho)

コメントで言及されているように、data.tableパッケージもこれに優れていますが、そのコードは読者の演習として残します。

ただし、上で述べたように、get.rho関数が遅い場合は、サブセット化とループの手法がどれほど巧妙であっても、計算に時間がかかります。


投稿の関数コードを編集します。

これが時系列データ、またはそのように扱うことができるデータである場合、この種のラグ比較を行う多くのパッケージと関数があります。私はそれらに精通しているわけではありませんが、Google と CRAN のタスク ビューをざっと見てみると、オプションの優れた概要がわかります。

lmベンチマークはしていませんが、コードの最も遅いセクションが呼び出しにあると想定しても安全だと思います。フルセットではなくデータの一部でこれを行うsampleと、劇的にスピードアップします。しかし、誰かがはるかに優れた完全なソリューションを持っていると確信しています。

于 2012-06-26T15:30:12.767 に答える