2016-01-02 11 views
6

私のデータフレームには、欠損値を含む変数が"NA"のような文字列として含まれています。これらを含むデータフレーム内のすべての列を解析し、is.na()などの機能によってキャッチされた実際のNAsに変換する最も効率的な方法は何ですか?"NA"文字列の引用符を解析する

私はsqldfを使用してデータベースに問い合わせています。

再現例:

vect1 <- c("NA", "NA", "BANANA", "HELLO") 
vect2 <- c("NA", 1, 5, "NA") 
vect3 <- c(NA, NA, "NA", "NA") 


df = data.frame(vect1,vect2,vect3) 
+5

データを読み取っているときは、これらを処理するのが最善の方法です。標準ツールで読み込んでいる場合は、 'na.strings'引数を見てください。それ以外の場合は[こちら](http://stackoverflow.com/questions/9351089/replacing-missing-values-coded-by-in-an-r-dataframe)が役立ちますが、期間をNA – user20650

+0

と置き換えてくださいツール?私はデータを読むときにこれらを扱うことが難しいかもしれないSQLデータベースからすべてのデータを読んでいます – jgozal

+0

大丈夫、あなたは特に何を使用していますか?かなり確かに彼らはna.strings引数を持っています – user20650

答えて

5

が選択肢に追加するには、あなたはまた、典型的なblah[index] <- NAアプローチの代わりにreplaceを使用することができます。考慮すべきもう一つの選択肢はtype.convertある

df <- replace(df, df == "NA", NA) 

replaceは次のようになります。これは、列の型を自動的に変換するためにデータを読み込むときにRが使用する関数です。したがって、結果は、現在の方法とは異なります。たとえば、2番目の列が数値に変換されるなどです。

df[] <- lapply(df, function(x) type.convert(as.character(x), na.strings = "NA")) 
df 

ここでの性能比較です。サンプルデータは@ rolandの答えです。ここで

はテストに機能している:

funop <- function() { 
    df[df == "NA"] <- NA 
    df 
} 

funr <- function() { 
    ind <- which(vapply(df, function(x) class(x) %in% c("character", "factor"), FUN.VALUE = TRUE)) 
    as.data.table(df)[, names(df)[ind] := lapply(.SD, function(x) { 
    is.na(x) <- x == "NA" 
    x 
    }), .SDcols = ind][] 
} 

funam1 <- function() replace(df, df == "NA", NA) 

funam2 <- function() { 
    df[] <- lapply(df, function(x) type.convert(as.character(x), na.strings = "NA")) 
    df 
} 

は、ここでのベンチマークです:

library(microbenchmark) 
microbenchmark(funop(), funr(), funam1(), funam2(), times = 10) 
# Unit: seconds 
#  expr  min  lq  mean median  uq  max neval 
# funop() 3.629832 3.750853 3.909333 3.855636 4.098086 4.248287 10 
# funr() 3.074825 3.212499 3.320430 3.279268 3.332304 3.685837 10 
# funam1() 3.714561 3.899456 4.238785 4.065496 4.280626 5.512706 10 
# funam2() 1.391315 1.455366 1.623267 1.566486 1.606694 2.253258 10 

replaceはjgozalさん@と同じであるローランドのアプローチ、@と同じになります。ただし、type.convertのアプローチでは、異なる列の種類が発生します。

all.equal(funop(), setDF(funr())) 
all.equal(funop(), funam()) 

str(funop()) 
# 'data.frame': 10000000 obs. of 3 variables: 
# $ vect1: Factor w/ 3 levels "BANANA","HELLO",..: 2 2 NA 2 1 1 1 NA 1 1 ... 
# $ vect2: Factor w/ 3 levels "1","5","NA": NA 2 1 NA 1 NA NA 1 NA 2 ... 
# $ vect3: Factor w/ 1 level "NA": NA NA NA NA NA NA NA NA NA NA ... 

str(funam2()) 
# 'data.frame': 10000000 obs. of 3 variables: 
# $ vect1: Factor w/ 2 levels "BANANA","HELLO": 2 2 NA 2 1 1 1 NA 1 1 ... 
# $ vect2: int NA 5 1 NA 1 NA NA 1 NA 5 ... 
# $ vect3: logi NA NA NA NA NA NA ... 
4

私はthis質問からそれをやって、この素敵な方法を見つけた:

したがって、この特定の状況のた​​めに、それだけで次のようになります。

df[df=="NA"]<-NA 

これだけかかりました5百万行と約250変数で約30秒

+0

これは、たとえばdata.tableパッケージを使用して、これをはるかに迅速に行うことができます。しかし、あなたは 'df'の再現可能な例を提供していないので、答えを構成してテスト/ベンチマークすることができません。 – Roland

+0

再現可能な例が追加されました – jgozal

4

これはわずかに速い:

set.seed(42) 
df <- do.call(data.frame, lapply(df, sample, size = 1e7, replace = TRUE)) 
df2 <- df 
system.time(df[df=="NA"]<-NA) 
# user  system  elapsed 
#3.601  0.378  3.984 

library(data.table) 
setDT(df2) 
system.time({ 
    #find character and factor columns 
    ind <- which(vapply(df2, function(x) class(x) %in% c("character", "factor"), FUN.VALUE = TRUE)) 
    #assign by reference 
    df2[, names(df2)[ind] := lapply(.SD, function(x) { 
    is.na(x) <- x == "NA" 
    x 
}), .SDcols = ind] 
}) 
# user  system  elapsed 
#2.484  0.190  2.676 
all.equal(df, setDF(df2)) 
#[1] TRUE 
関連する問題