2016-07-21 5 views
1

ロットの列を持つ非常に大きなデータフレームでNAsを再コードしようとしています。私は、名前のベクトル(median.to.replace)の異なる列の文字ベクトル(num_var)と置換値に列名を格納しました。 各カラムでは、NAsはmedian.to.replaceの正しい値に置き換えてください。'seq_along'名前付きカラムを使用して、NAsを適切な値に置き換えます。

seq_alongループ内のコードを使用して、手動でコードを実行すると、私はすべてのNASは記録されません。この単純なコードを試してみて、いくつかのNAが置き換えられますただし、各列名を手動

を指定するには問題ありません間違った値??

for (name_col in seq_along(num_var)) 
{ 
    na_rows <- is.na(allProspect.tst[,name_col]) 
    allProspect.tst[na_rows,name_col] <- median.to.replace[name_col] 

} 

誰に何が間違っているのかを示すポインタがありますか?これに高速かつメモリ効率の良いアプローチを使用しようとしています

+3

ようこそStackOverflow。 [MCVE] –

+0

を提供してください。 'seq_along'は、1から' length(num_var) 'までの整数ベクトルを生成します。 data.frame(ID変数など)の列をスキップしている場合、適切にインデックスを作成していません。 – lmo

+0

はmedian.to.replace a vectorですか? – aichao

答えて

1

は、ベクトルnum_varは、データフレームの最初の列で開始しないと隣接していないんので、あなたのコメントによると、あなたはこの

# simple example with just four columns 
allProspect.tst <- data.frame(one=c(1:3,8), two=c(NA,4:6), three=1:4, four= c(5,NA,7, 8)) 
# want to replace NAs in columns "two" and "four" with values 5 and 7, respectively 
num_var <- c("two","four") 
median.to.replace <- c(5, 7) 
# let's see the data before replacement 
print(allProspect.tst) 
## one two three four 
##1 1 NA  1 5 
##2 2 4  2 NA 
##3 3 5  3 7 
##4 8 6  4 8 

# just loop over the collection of column names (not indices) 
for (name_col in num_var) { 
    na_rows <- is.na(allProspect.tst[,name_col]) 
    # key is to get the corresponding element in median.to.replace 
    # using which() index in num_var has value equal name_col 
    allProspect.tst[na_rows,name_col] <- median.to.replace[which(num_var==name_col)] 
} 
# now let's see the replaced data 
print(allProspect.tst) 
## one two three four 
##1 1 5  1 5 
##2 2 4  2 7 
##3 3 5  3 7 
##4 8 6  4 8 

アップデートが必要になります。それをより効率的に

多数の列に対して置換操作を効率化する方法はたくさんありますが、最も基本的なものは*applyファミリの関数look here for an excellent overview、R baseパッケージから入手可能である。次のように更新されたコードは次のとおり

replace.with.median <- function(col, median.val, df) { 
    na_rows <- is.na(df[, col]) 
    df[na_rows, col] <- median.val 
    return(df[, col]) 
} 
allProspect.tst[, num_var] <- mapply(replace.with.median, num_var, median.to.replace, 
            MoreArgs=list(df=allProspect.tst)) 
print(allProspect.tst) 
## one two three four 
##1 1 5  1 5 
##2 2 4  2 7 
##3 3 5  3 7 
##4 8 6  4 8 

  1. forループの本体は関数replace.with.median中に封入されています。入力引数は、次のとおり

    • colmedian.to.replace
    • dfから対応する代替値:

    データを含むデータフレーム

  2. median.valを交換するNA Sを見つけるために、列名この関数はcol列をdfから返します。NAをmedian.valに置き換えます。

  3. 上記のリンクに記載の使用mapply、:あなたは、いくつかのデータ構造(例えばベクトル、リスト)があり、それぞれの第一の要素に関数を適用したいときのために

    、および各2番目の要素など、

    はここで、私たちはお互いに「ロックステップ」で二つのベクトルnum_varmedian.to.replace上で機能replace.with.medianを適用したいです。さらに、データフレームallProspect.tstreplace.with.medianMoreArgs引数のmapplyで提供します。

  4. mapplyから返されるものは、NAが置き換えられた列ベクトルのコレクションです。 allProspect.tstの対応する列をこれらと置き換えます。

これが役に立ちます。

+0

非常に役に立ちました!私は自分のコードを修正し、あなたが提案したような正しいループ構造を使用しました。蘭は非常に効率的で、わずか数秒で約9ミルをコードすることができます。行と40列。 "mapply"自分自身を見つけましたが、私の問題にそれを適用する方法を理解できませんでした。あなたの例は、私が実際にそれを適用する方法を理解する助けになりました。 – wabe

1

data.frameではなくdata.tableを使用すると、これはもっと速く動作します。ここでは、mtcarsデータセットの値が欠落しているランダムなデータセットを作成し、それらの欠損値を置き換えるためにルックアップテーブルを使用しました。

library(data.table) 
set.seed(44) 
f_dowle<-function(DT,value=-1,col) { #copied and edited this function from elsewhere 
    set(DT,which(is.na(DT[[col]])),col,value) 
} 

data(mtcars) 

setDT(mtcars) 

for(i in colnames(mtcars)){ 
    rand_na<-sample(1:nrow(mtcars),3) 
    mtcars[rand_na,eval(as.name(i)):=NA] 

} 
head(mtcars) #showing random missing values 

     mpg cyl disp hp drat wt qsec vs am gear carb 
1: 21.0 NA 160 NA 3.90 2.620 16.46 0 1 4 4 
2: 21.0 6 NA 110 3.90 NA 17.02 0 1 4 4 
3: 22.8 4 108 NA 3.85 2.320 18.61 1 1 4 1 
4: 21.4 6 NA 110 3.08 3.215 19.44 1 0 3 1 
5: 18.7 NA 360 175 NA 3.440 17.02 0 0 3 2 
6: 18.1 6 225 105 2.76 NA 20.22 1 0 3 1 

lkp_dt<-data.table(column=colnames(mtcars),value=1:11) 
for(i in colnames(mtcars)){ 
    value=lkp_dt[column==i,value] 
    f_dowle(mtcars,value=value,col=i) 

} 

head(mtcars) #missing values replaced 

    mpg cyl disp hp drat wt qsec vs am gear carb 
1: 21.0 2 160 4 3.90 2.620 16.46 0 1 4 4 
2: 21.0 6 3 110 3.90 6.000 17.02 0 1 4 4 
3: 22.8 4 108 4 3.85 2.320 18.61 1 1 4 1 
4: 21.4 6 3 110 3.08 3.215 19.44 1 0 3 1 
5: 18.7 2 360 175 5.00 3.440 17.02 0 0 3 2 
6: 18.1 6 225 105 2.76 6.000 20.22 1 0 3 1 
+0

素敵な例!しかし、私の最初の列は "1"で始まらず、列番号は連続していません。あなたの例をこのような状況に適応させる方法をあまり理解していない。例えば、私は "3"、 "7"、 "22"、 "97"をmedian.to.replace [1,2,3,4]で再コードしたいと思います。実際にもっと多くの欄 – wabe

+0

@インクルードする列 - 手動でリストを作成したり、値のない列をチェックしたりすることができます。ルックアップテーブルに関しては、これはあなたが望むものであれば何でも構いません。これらの列の中央値を再コード化する場合は、ルックアップ・テーブルに入れるか、関数を使用して表自体から直接計算します。 – Jason

関連する問題