私は この質問 に似たものを達成しようとしていますが、NAで置き換える必要のある複数の値と、大きなデータセットを使用しています。
df <- data.frame(name = rep(letters[1:3], each = 3), foo=rep(1:9),var1 = rep(1:9), var2 = rep(3:5, each = 3))
これはこのデータフレームを生成します:
df
name foo var1 var2
1 a 1 1 3
2 a 2 2 3
3 a 3 3 3
4 b 4 4 4
5 b 5 5 4
6 b 6 6 4
7 c 7 7 5
8 c 8 8 5
9 c 9 9 5
たとえば、3と4のすべての出現箇所をNAで置き換えたいのですが、 "var"で始まる列のみです。
[]
演算子の組み合わせを使用して、必要な結果を得ることができることを知っています。
df[,grep("^var[:alnum:]?",colnames(df))][
df[,grep("^var[:alnum:]?",colnames(df))] == 3 |
df[,grep("^var[:alnum:]?",colnames(df))] == 4
] <- NA
df
name foo var1 var2
1 a 1 1 NA
2 a 2 2 NA
3 a 3 NA NA
4 b 4 NA NA
5 b 5 5 NA
6 b 6 6 NA
7 c 7 7 5
8 c 8 8 5
9 c 9 9 5
今私の質問は次のとおりです:
|
演算子で区切られた不必要な一連の条件を実行する必要がある複数の値を指定する方法はありますか?replace
を使用してこれを行うこともできます:
sel <- grepl("var",names(df))
df[sel] <- lapply(df[sel], function(x) replace(x,x %in% 3:4, NA) )
df
# name foo var1 var2
#1 a 1 1 NA
#2 a 2 2 NA
#3 a 3 NA NA
#4 b 4 NA NA
#5 b 5 5 NA
#6 b 6 6 NA
#7 c 7 7 5
#8 c 8 8 5
#9 c 9 9 5
100万行のサンプルデータを使用した簡単なベンチマークは、これが他の回答よりも速いことを示唆しています。
あなたも行うことができます:
col_idx <- grep("^var", names(df))
values <- c(3, 4)
m1 <- as.matrix(df[,col_idx])
m1[m1 %in% values] <- NA
df[col_idx] <- m1
df
# name foo var1 var2
#1 a 1 1 NA
#2 a 2 2 NA
#3 a 3 NA NA
#4 b 4 NA NA
#5 b 5 5 NA
#6 b 6 6 NA
#7 c 7 7 5
#8 c 8 8 5
#9 c 9 9 5
このオプションの時間は決めていませんが、makemeNA
という関数を作成しました。これは my GitHub-only "SOfun"パッケージ の一部です。
その関数を使用すると、アプローチは次のようになります。
library(SOfun)
Cols <- grep("^var", names(df))
df[Cols] <- makemeNA(df[Cols], NAStrings = as.character(c(3, 4)))
df
# name foo var1 var2
# 1 a 1 1 NA
# 2 a 2 2 NA
# 3 a 3 NA NA
# 4 b 4 NA NA
# 5 b 5 5 NA
# 6 b 6 6 NA
# 7 c 7 7 5
# 8 c 8 8 5
# 9 c 9 9 5
関数はna.strings
のtype.convert
引数を使用して、NA
への変換を行います。
以下を使用してパッケージをインストールします。
library(devtools)
install_github("SOfun", "mrdwab")
(またはGitHubからパッケージをインストールするお気に入りの方法)。
ここにいくつかのベンチマークがあります。物事を面白くし、数値と非数値の両方をNA
に置き換えて、物事の比較を確認することにしました。
これがサンプルデータです:
n <- 1000000
set.seed(1)
df <- data.frame(
name1 = sample(letters[1:3], n, TRUE),
name2 = sample(letters[1:3], n, TRUE),
name3 = sample(letters[1:3], n, TRUE),
var1 = sample(9, n, TRUE),
var2 = sample(5, n, TRUE),
var3 = sample(9, n, TRUE))
テストする関数は次のとおりです。
fun1 <- function() {
Cols <- names(df)
df[Cols] <- makemeNA(df[Cols], NAStrings = as.character(c(3, 4, "a")))
df
}
fun2 <- function() {
values <- c(3, 4, "a")
col_idx <- names(df)
m1 <- as.matrix(df)
m1[m1 %in% values] <- NA
df[col_idx] <- m1
df
}
fun3 <- function() {
values <- c(3, 4, "a")
col_idx <- names(df)
val_idx <- sapply(df[col_idx], "%in%", table = values)
is.na(df[col_idx]) <- val_idx
df
}
fun4 <- function() {
sel <- names(df)
df[sel] <- lapply(df[sel], function(x)
replace(x, x %in% c(3, 4, "a"), NA))
df
}
fun2
とfun3
を分割します。 fun2
は、すべてを同じ型に変換するので、私は夢中です。 fun3
も遅いと思います。
system.time(fun2())
# user system elapsed
# 4.45 0.33 4.81
system.time(fun3())
# user system elapsed
# 34.31 0.38 34.74
だから今、それは私とシーラにかかっています...
library(microbenchmark)
microbenchmark(fun1(), fun4(), times = 50)
# Unit: seconds
# expr min lq median uq max neval
# fun1() 2.934278 2.982292 3.070784 3.091579 3.617902 50
# fun4() 2.839901 2.964274 2.981248 3.128327 3.930542 50
Thela、ありがとう!
ここにアプローチがあります:
# the values that should be replaced by NA
values <- c(3, 4)
# index of columns
col_idx <- grep("^var", names(df))
# [1] 3 4
# index of values (within these columns)
val_idx <- sapply(df[col_idx], "%in%", table = values)
# var1 var2
# [1,] FALSE TRUE
# [2,] FALSE TRUE
# [3,] TRUE TRUE
# [4,] TRUE TRUE
# [5,] FALSE TRUE
# [6,] FALSE TRUE
# [7,] FALSE FALSE
# [8,] FALSE FALSE
# [9,] FALSE FALSE
# replace with NA
is.na(df[col_idx]) <- val_idx
df
# name foo var1 var2
# 1 a 1 1 NA
# 2 a 2 2 NA
# 3 a 3 NA NA
# 4 b 4 NA NA
# 5 b 5 5 NA
# 6 b 6 6 NA
# 7 c 7 7 5
# 8 c 8 8 5
# 9 c 9 9 5
dplyr
はこのタスクに非常に適していると思います。
@ thelatemailで提案されているようにreplace()
を使用すると、次のようなことができます。
library("dplyr")
df <- df %>%
mutate_at(vars(starts_with("var")),
funs(replace(., . %in% c(3, 4), NA)))
df
# name foo var1 var2
# 1 a 1 1 NA
# 2 a 2 2 NA
# 3 a 3 NA NA
# 4 b 4 NA NA
# 5 b 5 5 NA
# 6 b 6 6 NA
# 7 c 7 7 5
# 8 c 8 8 5
# 9 c 9 9 5
ここにdplyrソリューションがあります:
# Define replace function
repl.f <- function(x) ifelse(x%in%c(3,4), NA,x)
library(dplyr)
cbind(select(df, -starts_with("var")),
mutate_each(select(df, starts_with("var")), funs(repl.f)))
name foo var1 var2
1 a 1 1 NA
2 a 2 2 NA
3 a 3 NA NA
4 b 4 NA NA
5 b 5 5 NA
6 b 6 6 NA
7 c 7 7 5
8 c 8 8 5
9 c 9 9 5