R:

2012-03-16 8 views
0

私はデータセットの次のタイプ持って適用してループを書き換える:R:

id;2011_01;2011_02;2011_03; ... ;2001_12 
id01;NA;NA;123; ... ;NA 
id02;188;NA;NA; ... ;NA 

で毎月、各行は、一意の顧客であり、各列は(過去10年から、この顧客の形質を示します独自の列を持つ)。この120カラムのデータフレームを10カラムのデータフレームに凝縮したいのですが、これはほとんどの行が(月自体は変わるかもしれませんが)毎年1回または0回の観測があることがわかっているからです。

私はすでにこれは、ネストされた場合、句でループを使用して、1年時に、やった:

for(i in 1:nrow(input_data)) { 
    temp_row <- input_data[i,c("2011_01","2011_02","2011_03","2011_04","2011_05","2011_06","2011_07","2011_08","2011_09","2011_10","2011_11", "2011_12")] 
    loc2011 <- which(!is.na(temp_row)) 
    if(length(loc2011) > 0) { 
     temp_row_2011[i,] <- temp_row[loc2011[1]] #pick the first observation if there are several 
    } else { 
     temp_row_2011[i,] <- NA 
    } 
} 

私のデータセットはかなり大きいです、と私は上記のループを実行する必要があるので、 10回(毎年1回)、これは時間がかかりすぎている。 Rでapplyコマンドを使用するほうがはるかに優れていることを知っていますので、この作業について助けていただければ幸いです。どのように私は全体のことを(別の年を含む)より良い書き込みすることができますか?

答えて

3

は、あなたはそれがより速くあなたのループよりも実行さ場合、これはあなたの右出力、およびを与える場合はこのようなものが

temp_row_2011 <- apply(input_data, 1, function(x){ 
     temp_row <- x[c("2011_01","2011_02","2011_03","2011_04","2011_05","2011_06","2011_07","2011_08","2011_09","2011_10","2011_11", "2011_12")] 
     temp_row[!is.na(temp_row)][1] 
    }) 

を?:した後、それは必ずしも唯一の事実によるものではありませんですapply()を使用していますが、割り当ての数が少なく、if {}else {}を避けるためです。あなたはそれが匿名関数をコンパイルすることにより、さらに高速行かせることができるかもしれません:

reduceyear <- function(x){ 
     temp_row <- x[c("2011_01","2011_02","2011_03","2011_04","2011_05","2011_06","2011_07","2011_08","2011_09","2011_10","2011_11", "2011_12")] 
     temp_row[!is.na(temp_row)][1] 
    } 
    # compile, just in case it runs faster: 
    reduceyear_c <- compiler:::cmpfun(reduceyear) 
    # this ought to do the same as the above. 
    temp_row_2011 <- apply(input_data, 1, reduceyear_c) 

あなたはinput_datadata.framematrixであるかどうか言ってませんでしたが、行列は前者よりも速く(だけ有効になりますinput_dataがすべて同じクラスのデータである場合)。

[EDIT:フル例えば、DWINによって動機付け]

input_data <- matrix(ncol=24,nrow=10) 
    # years and months: 
    colnames(input_data) <- c(paste(2010,1:12,sep="_"),paste(2011,1:12,sep="_")) 
    # some ids 
    rownames(input_data) <- 1:10 
    # put in some values: 
    input_data[sample(1:length(input_data),200,replace=FALSE)] <- round(runif(200,100,200)) 
    # make an all-NA case: 
    input_data[2,1:12] <- NA 

    # and here's the full deal: 
    sapply(2010:2011, function(x,input_data){ 
     input_data_yr <- input_data[, grep(x, colnames(input_data))] 
     apply(input_data_yr, 1, function(id){ 
        id[!is.na(id)][1] 
       } 
     ) 
    }, input_data) 

すべてNA場合の動作。 grep() DWinから列選択のアイデアを取り上げました。上記の例のように、匿名の内部関数を実際に定義し、コンパイルして潜在的に物事をより速くすることができます。

+0

ありがとう。私はすでにあなたの前のコードをテストして、それが私が探していたビルディングブロックであるように思えました。今週末にこのコードを使用してプロセス全体を自動化しようとします。いいアドバイス。 – Joshua

1

私は小さなテストケースを作成しました(そのためには、ティムリフの提案は失敗します)。 2年間4四半期などのより完全なテストケースを作成し、すべてのNAなどの病理学的なケースを1年の1つの行に含めるコードを記述することで、より多くの関心を引くことができます。私は年ごとの列を名前で書く必要があるのではなく、grep()戦略で循環させるべきだと思うでしょう:

# funyear <- function to work on one year's data and return a single vector 
    # my efforts keep failing on the all(NA) row by year combos 
    sapply(seq("2011", "2001"), function (pat) funyear(input_data[grep(pat, names(input_data))]) 
+1

チェックしてくれてありがとう、私は例を更新しました。 –

+0

次回サンプルデータを投稿します。 – Joshua