2016-08-03 8 views
0

私の質問はとても簡単です。私は、100行以上の各行にさまざまな数値のデータフレームを持っています。最初の列は常にゼロ以外の数値です。私がしたいのは、各行(最初の列を除く)の最初の数字を最初の列(最初の列の値)で置き換えることです。行ごとの値を最初の列の値に置き換えてください。

ifelseの行とforあなたは、データがそれほど大きくはないですので、それを行うためのシンプルなベクトル化方法がなければならないの行を反復処理するが、ループ...

+0

テストとデモンストレーションに適した例を投稿してください。 –

答えて

1

は別のアプローチは、単純なループを使用することをお勧めsapplyを使用すると、ループ処理よりも効率的です。あなたのデータを仮定すると、データフレームdfである:ここでは

df[,-1] <- sapply(df[,-1], function(x) {ind <- which(x!=0); x[ind] = df[ind,1]; return(x)}) 

、私たちは、それぞれの上にfunctionと最初の列を除くdfのすべての列を適用しています。 functionにおいて、xは、順番に、これらの列のそれぞれである:

  1. まずwhichを使用してゼロであり、列の行インデックスを見つけます。
  2. これらの行をxに設定して、最初の列の行の対応する値をdfに設定します。
  3. 機能で操作が列の上にすべての「ベクトル化」であることを柱

注意を返します。つまり、列の行をループしません。 sapplyの結果は、最初の列ではないdfのすべての列を置き換える処理済み列の行列です。

*applyファミリの機能の優れたレビューについては、thisを参照してください。

これが役に立ちます。

+0

優れています。ありがとうございました。好奇心の念から、各列ではなく各行で同じことを行うために適用することはできませんでしたか? –

+0

'apply'は、配列のある次元にわたって関数を適用するためのものです。良いことは、[このSOの答え](http://stackoverflow.com/questions/3505701/r-grouping-functions-sapply-vs-lapply-vs-apply-vs-tapply-vs-by-vs-aggrega)を参照してください'* apply'ファミリーの機能のレビュー – aichao

+0

これは私が欲しかったことをしていないようですが、それはちょうど== 0を!= 0に変更する場合です。 **すべての** nonzeros **を各行の最初の番号に変更したいと思います。私のiPadからの投稿はまだ試していませんでした –

1

、私はあなたが

for (i in 1:nrow(mydata)) 
{ 
for (j in 2:ncol(mydata) 
    { 

    mydata[i,j]<- ifelse(mydata[i,j]==0 ,0 ,mydata[i,1]) 
    } 
} 
+0

ありがとうございました。しかし、データセットは実際には非常に大きく、私はこれを行うためにベクトル化された/ rの方法を探しています。また、あなたのソリューションでは、最初の列データも置き換えられませんか?私は最初の列がそのまま残る必要があります。 –

+0

そして私が間違っていなければifelseの最後にmydata [1、j]の代わりにmydata [i、1]でなければなりません –

+0

間違いをおかけして申し訳ありません。これは主に今の時点でマルチタスキングのためです:)あなたの2番目の問題が解決された新しい変更を期待しています。私は、これがこの問題を解決する最も効率的な方法ではないことに同意します。私は他の人がこの問題にどのようにアプローチしているかを見るために答えを見ることに興味があります。 – MFR

1

は、私はあなたのための完全にベクトル化ソリューション持って、あなたのデータフレームがdatであると仮定します。

mat <- as.matrix(dat[, -1]) 
pos <- which(mat != 0) 
mat[pos] <- rep(dat[[1]], times = ncol(mat))[pos] 
new_dat <- "colnames<-"(cbind.data.frame(dat[1], mat), colnames(dat)) 

例を

set.seed(0) 
dat <- "colnames<-"(cbind.data.frame(1:5, matrix(sample(0:1, 25, TRUE), 5)), 
        c("val", letters[1:5])) 
# val a b c d e 
#1 1 1 0 0 1 1 
#2 2 0 1 0 0 1 
#3 3 0 1 0 1 0 
#4 4 1 1 1 1 1 
#5 5 1 1 0 0 0 

私のコードは、上記得られます

# val a b c d e 
#1 1 1 0 0 1 1 
#2 2 0 2 0 0 2 
#3 3 0 3 0 3 0 
#4 4 4 4 4 4 4 
#5 5 5 5 0 0 0 

ベンチマークが必要ですか?

set.seed(0) 
n <- 2000 ## use a 2000 * 2000 matrix 
dat <- "colnames<-"(cbind.data.frame(1:n, matrix(sample(0:1, n * n, TRUE), n)), 
        c("val", paste0("x",1:n))) 

## have to test my solution first, as aichao's solution overwrites `dat` 

## my solution 
system.time({mat <- as.matrix(dat[, -1]) 
      pos <- which(mat != 0) 
      mat[pos] <- rep(dat[[1]], times = ncol(mat))[pos] 
      "colnames<-"(cbind.data.frame(dat[1], mat), colnames(dat))}) 
# user system elapsed 
# 0.352 0.056 0.410 

## solution by aichao 
system.time(dat[,-1] <- sapply(dat[,-1], function(x) {ind <- which(x!=0); x[ind] = dat[ind,1]; x})) 
# user system elapsed 
# 7.804 0.108 7.919 

私のソリューションは20倍高速です!

+0

あなたのコードを再現して理解しようとはしませんでしたが、結果は私が望むものではありません。私は非0に各行の最初の数字の値を与えたい、あなたの解は0を最初の数字に変更する –

+1

私は理解しやすい解決法を受け入れ、@aichaoは徹底的な説明彼のコードの働き初心者としては絶対最大のパフォーマンスよりも重要ですが、これは終わりまでのレースではなく、rについてもっと学習するエクササイズです。 –

関連する問題