2017-12-06 6 views
0

13個の列のいずれかに多数のコードのいずれかが含まれている場合は1、それ以外の場合は0のフラグを作成します。データがデータベースに格納されているため、dplyrを使用する必要があります。私は多くの%inステートメントを使って、私が達成したことを達成することができます。私はこのコードを書くためのより簡潔な方法があるのだろうかと思います。左側に複数の変数を許す%inのバージョンがありますか?複数の%inステートメントを1行のdplyrコードに置き換えてください

次のコードは正しい結果を示します。私は簡潔さのためにわずか5列と2列を含んだ。

library(dplyr) 

match_dx <- c(paste0("C0", 0:9), paste0("C", 10:20)) 

df <- tibble(dx1 = c("C00", "G01"), 
    dx2 = c("C50", "Z11"), 
    dx3 = c("D20", "D22"), 
    dx4 = c("A40", "C21"), 
    dx13 = c("G20", "C30")) 

df %>% 
mutate(flag = case_when(
     dx1 %in% match_dx ~ 1, 
     dx2 %in% match_dx ~ 1, 
     dx3 %in% match_dx ~ 1, 
     dx4 %in% match_dx ~ 1, 
     dx13 %in% match_dx ~ 1, 
     T ~ 0 
)) 

私は

df %>% 
mutate(flag = case_when(
     any(vars(dx1:dx13) %in% match_dx) ~ 1, 
     T ~ 0 
)) 

これが作業を行いますが、おそらく似たようなまたは変数ごとに1行を必要とせずにこれを達成する別の方法があるようなものがあるかどうかを知りたいです。

ありがとうございます!

+0

あなたはおそらく '様々な答えをmicrobenchmark'必要があります。私の賭けは「適用」が最も速く、最小のメモリしか使用しない。 – hrbrmstr

+0

すべての答えをありがとう。私はそれらを試しています。私はデータベースのバックエンドを使用しているので、dplyrコードをSQLに変換する必要があることに注意してください。 –

+0

@thelatemailあなたは答えを出しましたか?私はそれを見ない。 – hrbrmstr

答えて

3

applymutateを使用すると、すべての列を一度に比較できます。ここで

library(dplyr) 

df %>% 
    mutate(flag = apply(., 1, function(x) any(x %in% match_dx) * 1)) 
# # A tibble: 2 x 6 
#  dx1 dx2 dx3 dx4 dx13 flag 
# <chr> <chr> <chr> <chr> <chr> <dbl> 
# 1 C00 C50 D20 A40 G20  1 
# 2 G01 Z11 D22 C21 C30  0 
4

gatherずつのオプションは、それがにreduceその後、

library(tidyverse) 
df %>% 
    rownames_to_column('rn') %>% 
    gather(key, val, -rn) %>% group_by(rn) %>% 
    mutate(flag = as.integer(any(val %in% match_dx))) %>% 
    spread(key, val) 
# A tibble: 2 x 7 
# Groups: rn [2] 
#  rn flag dx1 dx13 dx2 dx3 dx4 
#* <chr> <int> <chr> <chr> <chr> <chr> <chr> 
#1  1  1 C00 G20 C50 D20 A40 
#2  2  0 G01 C30 Z11 D22 C21 

または論理列を作成するmutate_allを使用して、「ワイド」にそれを「長い」形式にすると、その後spreadです単一の論理ベクトルとmutateを使用して 'フラグ'を作成します。

df %>% 
    mutate_all(funs(. %in% match_dx)) %>% 
    reduce(`|`) %>% 
    as.integer %>% 
    mutate(df, flag = .) 
# A tibble: 2 x 6 
#  dx1 dx2 dx3 dx4 dx13 flag 
# <chr> <chr> <chr> <chr> <chr> <int> 
#1 C00 C50 D20 A40 G20  1 
#2 G01 Z11 D22 C21 C30  0 

それとも@thelatemail

df$flag <- as.integer(Reduce(`|`, lapply(df, is.element, set=match_dx))) 

それとも%in%

as.integer(Reduce(`|`, lapply(df, `%in%`, match_dx))) 
+1

私は基底Rで 'Reduce'を提案しようとしていましたが、これはとにかくオプション#2でカバーします。後継のために 'as.integer(Reduce(\' | \ '、lapply(df、is.element、set = match_dx)))' – thelatemail

+0

@ is.element'は '%in% 'と似ています – akrun

+1

これは私が信じているのと同じです。もっと多くの' 'バッククォート – thelatemail

3

NOTEを使用して提案しReduce/lapplybase Rオプションを使用します。私は、これらの中で-DBのSQL OPSされるようにする必要性を見落とし。これはうまくいかないでしょう。 purrrを使用して

library(dplyr) 
library(purrrlyr) 
library(purrr) 

df %>% 
    by_row(~{ as.numeric(any(. %in% match_dx)) }, .to="flag") %>% 
    mutate(flag = flatten_dbl(flag)) 
## # A tibble: 2 x 6 
##  dx1 dx2 dx3 dx4 dx13 flag 
## <chr> <chr> <chr> <chr> <chr> <dbl> 
## 1 C00 C50 D20 A40 G20  1 
## 2 G01 Z11 D22 C21 C30  0 
2

さらに別の代替:

library(dplyr) 
library(purrr) 

df %>% mutate(flag = map_int(transpose(.), ~ any(. %in% match_dx))) 
#> # A tibble: 2 x 6 
#>  dx1 dx2 dx3 dx4 dx13 flag 
#> <chr> <chr> <chr> <chr> <chr> <int> 
#> 1 C00 C50 D20 A40 G20  1 
#> 2 G01 Z11 D22 C21 C30  0