私の質問はとても簡単です。私は、100行以上の各行にさまざまな数値のデータフレームを持っています。最初の列は常にゼロ以外の数値です。私がしたいのは、各行(最初の列を除く)の最初の数字を最初の列(最初の列の値)で置き換えることです。行ごとの値を最初の列の値に置き換えてください。
ifelseの行とforあなたは、データがそれほど大きくはないですので、それを行うためのシンプルなベクトル化方法がなければならないの行を反復処理するが、ループ...
私の質問はとても簡単です。私は、100行以上の各行にさまざまな数値のデータフレームを持っています。最初の列は常にゼロ以外の数値です。私がしたいのは、各行(最初の列を除く)の最初の数字を最初の列(最初の列の値)で置き換えることです。行ごとの値を最初の列の値に置き換えてください。
ifelseの行とforあなたは、データがそれほど大きくはないですので、それを行うためのシンプルなベクトル化方法がなければならないの行を反復処理するが、ループ...
は別のアプローチは、単純なループを使用することをお勧めsapply
を使用すると、ループ処理よりも効率的です。あなたのデータを仮定すると、データフレームdf
である:ここでは
df[,-1] <- sapply(df[,-1], function(x) {ind <- which(x!=0); x[ind] = df[ind,1]; return(x)})
、私たちは、それぞれの上にfunction
と最初の列を除くdf
のすべての列を適用しています。 function
において、x
は、順番に、これらの列のそれぞれである:
which
を使用してゼロであり、列の行インデックスを見つけます。x
に設定して、最初の列の行の対応する値をdf
に設定します。注意を返します。つまり、列の行をループしません。 sapply
の結果は、最初の列ではないdf
のすべての列を置き換える処理済み列の行列です。
*apply
ファミリの機能の優れたレビューについては、thisを参照してください。
これが役に立ちます。
優れています。ありがとうございました。好奇心の念から、各列ではなく各行で同じことを行うために適用することはできませんでしたか? –
'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に変更する場合です。 **すべての** nonzeros **を各行の最初の番号に変更したいと思います。私のiPadからの投稿はまだ試していませんでした –
、私はあなたが
for (i in 1:nrow(mydata))
{
for (j in 2:ncol(mydata)
{
mydata[i,j]<- ifelse(mydata[i,j]==0 ,0 ,mydata[i,1])
}
}
ありがとうございました。しかし、データセットは実際には非常に大きく、私はこれを行うためにベクトル化された/ rの方法を探しています。また、あなたのソリューションでは、最初の列データも置き換えられませんか?私は最初の列がそのまま残る必要があります。 –
そして私が間違っていなければifelseの最後にmydata [1、j]の代わりにmydata [i、1]でなければなりません –
間違いをおかけして申し訳ありません。これは主に今の時点でマルチタスキングのためです:)あなたの2番目の問題が解決された新しい変更を期待しています。私は、これがこの問題を解決する最も効率的な方法ではないことに同意します。私は他の人がこの問題にどのようにアプローチしているかを見るために答えを見ることに興味があります。 – MFR
は、私はあなたのための完全にベクトル化ソリューション持って、あなたのデータフレームが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を最初の数字に変更する –
私は理解しやすい解決法を受け入れ、@aichaoは徹底的な説明彼のコードの働き初心者としては絶対最大のパフォーマンスよりも重要ですが、これは終わりまでのレースではなく、rについてもっと学習するエクササイズです。 –
テストとデモンストレーションに適した例を投稿してください。 –