2011-09-15 16 views
2

私は初心者のRユーザーで、40,000行と300列のデータセットで作業しようとしています。私は何をしたいのかという解決策を見いだしましたが、私のマシンはコードを実行するのに1時間以上かかるので、専門家のように速いソリューションで助けてくれると感じています(半分の時間でこれを行うことができます) 。私は最後に私の解決策を掲示します。2つの配列の間で特定の値を分割する

私は何をしたいことは以下の通りです:

  1. YYYYMMbucket列の値に基づいてNYNに各列NY1の平均値を計算します。

  2. 平均YYYYMMbucket値で元の値を除算します。ここで

私の元のデータセットのサンプルです:

 YYYYMMbucket NY1 NY2 NY3 NY4 
1  200701.3  0.309 NA 20.719 16260 
2  200701.3  0.265 NA 19.482 15138 
3  200701.3  0.239 NA 19.168 14418 
4  200701.3  0.225 NA 19.106 14046 
5  200701.3  0.223 NA 19.211 14040 
6  200701.3  0.234 NA 19.621 14718 
7  200701.3  0.270 NA 20.522 15780 
8  200701.3  0.298 NA 22.284 16662 
9  200701.2  0.330 NA 23.420 16914 
10  200701.2  0.354 NA 23.805 17310 
11  200701.2  0.388 NA 24.095 17448 
12  200701.2  0.367 NA 23.954 17640 
13  200701.2  0.355 NA 23.255 17748 
14  200701.2  0.346 NA 22.731 17544 
15  200701.2  0.347 NA 22.445 17472 
16  200701.2  0.366 NA 21.945 17634 
17  200701.2  0.408 NA 22.683 18876 
18  200701.2  0.478 NA 23.189 21498 
19  200701.2  0.550 NA 23.785 22284 
20  200701.2  0.601 NA 24.515 22368 

これは私の平均がどのように見えるかです:

 YYYYMMbucket NY1M  NY2M 
1  200701.1 0.4424574 NA 
2  200701.2 0.4530000 NA 
3  200701.3 0.2936935 NA 
4  200702.1 0.4624063 NA 
5  200702.2 0.4785937 NA 
6  200702.3 0.3091161 NA 
7  200703.1 0.4159687 NA 
8  200703.2 0.4491875 NA 
9  200703.3 0.2840081 NA 
10  200704.1 0.4279137 NA 

私が望む方法見える私の最終的な出力:

NY1avgs NY2avgs NY3avgs 
1 1.052117  NA 0.7560868 
2 0.9023011 NA 0.7109456 
3 0.8137734 NA 0.699487 
4 0.7661047 NA 0.6972245 
5 0.7592949 NA 0.7010562 
6 0.7967489 NA 0.7160181 
7 0.9193256 NA 0.7488978 
8 1.014663  NA 0.8131974 
9 0.7284768 NA 0.857904 




ここで私はそれをやった方法は次のとおりです。

まず、私は十分に簡単、私の平均値を計算するために "plyr" を使用:

test <- ddply(prf.delete2b,. (YYYYMMbucket), summarise, 
    NY1M = mean(NY1), NY2M = mean(NY2) ... ...)) 

は、次に使用次のシリーズ:

x <- c(1:40893) 

lookv <- function(x,ltab,rcol=2) ltab[max(which(ltab[,1]<=x)),rcol] 

NY1Fun <- function(x) (prf.delete2b$NY1[x]/lookv((prf.delete2b$YYYYMMbucket[x]),test,2)) 

NY2Fun <- function(x) (prf.delete2b$NY2[x]/lookv((prf.delete2b$YYYYMMbucket[x]),test,3)) 

NY1Avgs <- lapply(x, NY1Fun) 
NY2Avgs <- lapply(x, NY2Fun) 

私も言って上記の変種を試してみました:

NY1Fun <- function(x) (prf.delete2b$NY1[x]/subset(test, YYYYMMbucket == prf.delete2b$YYYYMMbucket[x], select =c(NY1M))) 

lapply(x, NY1Fun) 

NYnFunの各バリアントを実行するための良い20秒かかりますので、この300回をやってすることは非常に時間がかかりすぎます。誰もが私が投稿したものに任意の代替案を勧めたり、私が作った初心者の間違いを指摘できますか?

答えて

0

方法について:aveはその入力としてベクトルを同じ長さを返すため、この場合

test2 <- merge(prfdelete2b,test,all.x=TRUE) 
test2[2:ncol(prefdelete2b)]/test2[(ncol(prefdelete2b)+1):ncol(test2)] 
+0

これはとてもシンプルで、私が1分で欲しかったことを正確に行いました。ありがとう! – Kris

0

、私はaveの代わりddplyを使用します。 aveはベクトルを受け付けるだけなので、lapplyを使用してdata.frameの列をループする必要があります。

myFun <- function(x, groupVar) { 
    x/ave(x, groupVar, FUN=function(y) mean(y, na.rm=TRUE)) 
} 
relToMeans <- data.frame(prf.delete2b[1], 
    lapply(prf.delete2b[-1], myFun, groupVar=prf.delete2b[1])) 
+0

チップのおかげで、私はaveとddplyの違いを知らなかった。間違いなく便利になるでしょう。 – Kris

3

これはかなり慣習的なdata.tableのアプローチです。

# CREATE DUMMY DATA 
N = 1000 
mydf = data.frame(
    bucket = sample(letters, N, replace = T), 
    NY1 = runif(N), 
    NY2 = runif(N), 
    NY3 = runif(N), 
    NY4 = runif(N) 
) 

# SCALE COLUMNS BY AVG 
library(data.table) 
scale_x = function(x) x/ave(x) 
mydt = data.table(mydf) 
ans = mydt[,lapply(.SD, scale_x), by = 'bucket'] 
+1

すごく嬉しいです。これは私の元々の試みとはまったく異なっていたので、私は最後に試しましたが、どれくらい速く動作し、どの程度コードが必要なのかは信じられません。 – Kris

+1

これはうまくいきました。感謝は、 'data.table'パッケージを書いたMatt Dowleに行ってください:) – Ramnath

関連する問題