2017-11-23 19 views
0

他の列の値に基づいて新しい列を作成しようとしています。R:複数の列に変更して新しい列を作成する

ここに私が取り組んでいるものに似たデータセットがあります。 私は3つの変数、Test1、Test2、Test3を持っています。 Test変数のいずれかが DF60、DF61、DF63またはDF64または0の場合は1という新しい変数を作成しようとしています。

Test1<-c("DF64", "DF63", "DF89", "DF30", "DF70") 
Test2<-c("DF61", "DF25", "DF00", "DF30", "DF99") 
Test3<-c("DF80", "DF63", "DF60", "DF63", "DF70") 
Test<-data.frame(Test1, Test2, Test3) 

は、私は現時点では文ifelse多くを持っており、複数の値を可能にしながら、複数のテスト変数を超える ループを見上げすることができ、コードを探しています。

私はmutate_atを試しましたが、それは正しい方法ではないと思います。

Test2<- Test %>% 
mutate_at(vars(starts_with("Test")), funs(Test=ifelse("DF60" | "DF61" | 
"DF62" | "DF63", 1, 0))) 

ご協力いただきありがとうございます。

ありがとうございます!コメントの後

答えて

1
Test2<- Test %>% 
dplyr::select(starts_with("Test"))%>% 
mutate_all(function(x){x %in% c("DF60","DF61","DF62","DF63")})%>% 
mutate(out = ifelse(rowSums(.)<1,0,1)) 

調整が

あなたはyutannihilationによって提案されたとして、他の列、mutate_atを維持したい場合は、はるかに良いです。この問題は、選択された列でmutumで行を処理するようになります。次のことが最善の方法ですが、それが動作するかどうかは考え(私の前の質問に答え作り直さ:dplyr mutate on column subset (one function on all these columns combined))のドリスの答えは十分素敵ですが

library(tidyverse) 
library(anomalyDetection) 

Test1<-c("DF64", "DF63", "DF89", "DF30", "DF70") 
Test2<-c("DF61", "DF25", "DF00", "DF30", "DF99") 
Test3<-c("DF80", "DF63", "DF60", "DF63", "DF70") 
Test<-data.frame(Test1, Test2, Test3) 

Test$ExtraCol<-LETTERS[1:5] 


Test2<- Test %>% 
    mutate_at(vars(starts_with("Test")),funs(bin=.%in% c("DF60","DF61","DF62","DF63")))%>% 
    split(.,1<10)%>% 
    map_df(~mutate(.,out=rowSums(.[paste0("Test",1:3,"_bin")])>0)) 


    Test1 Test2 Test3 ExtraCol Test1_bin Test2_bin Test3_bin out 
    DF64 DF61 DF80  A  FALSE  TRUE  FALSE TRUE 
    DF63 DF25 DF63  B  TRUE  FALSE  TRUE TRUE 
    DF89 DF00 DF60  C  FALSE  FALSE  TRUE TRUE 
    DF30 DF30 DF63  D  FALSE  FALSE  TRUE TRUE 
    DF70 DF99 DF70  E  FALSE  FALSE  FALSE FALSE 
+0

ありがとうございます!すべての元の変数(Test1、Test2、Test3に加えて他の変数があります)を保持する方法はありますか?同じTest1、Test2、Tes3変数に基づいて複数の変数を作成する必要がありますので、変数を変更したくないです。 – user3047435

+0

ありがとうございます!申し訳ありませんが、この場合split(。、1 <10)は何をしますか? – user3047435

+0

splitは引数に基づいてdfをdfのリストに分割します。次のmap_dfは、それらのdfのそれぞれに引数を適用し、それらを1つのdfにバインドします。この場合、私は異なったdfのリストを望んでいませんでしたが、ただ一つのdf(df全体)のリストだけです。それは私が常に真実であるという議論に基づいて分割した理由です。必要であれば試してみることができます。この回答は前回の私のstackoverflowに関する質問に基づいています。リンクをたどると、 ) – Dries

1

、私はfuns()に関するいくつかの説明を追加してみましょうありません。

funs()は、接尾辞と式のペアを取ります。たとえば、あなたがsuffix1suffix2を指定した場合、あなたはその上に新しいTest1_suffix1という名前の列、Test1_suffix2Test2_suffix1Test2_suffix2となります:

funs(suffix1 = ..., suffix2 = ...) 

第二に、あなたは列ベクトルを表すために.を必要としています。

Test %>% 
    mutate_at(vars(starts_with("Test")), 
      funs(bin = ifelse(. == "DF60" | . == "DF61" | . == "DF62" | . == "DF63", 1, 0))) 
#> Test1 Test2 Test3 Test1_bin Test2_bin Test3_bin 
#> 1 DF64 DF61 DF80   0   1   0 
#> 2 DF63 DF25 DF63   1   0   1 
#> 3 DF89 DF00 DF60   0   0   1 
#> 4 DF30 DF30 DF63   0   0   1 
#> 5 DF70 DF99 DF70   0   0   0 

どうやら、%in%|のシーケンスよりも優れている:だから、あなたのifelse(...)の正しいバージョンは次のようにする必要があります。

Test %>% 
    mutate_at(vars(starts_with("Test")), 
      funs(bin = ifelse(. %in% c("DF60", "DF61", "DF62", "DF63"), 1, 0))) 
#> Test1 Test2 Test3 Test1_bin Test2_bin Test3_bin 
#> 1 DF64 DF61 DF80   0   1   0 
#> 2 DF63 DF25 DF63   1   0   1 
#> 3 DF89 DF00 DF60   0   0   1 
#> 4 DF30 DF30 DF63   0   0   1 
#> 5 DF70 DF99 DF70   0   0   0 

フィルタリングする場合は、filter_at()を使用できます。

Test %>% 
    filter_at(vars(starts_with("Test")), 
      any_vars(. %in% c("DF60", "DF61", "DF62", "DF63"))) 
#> Test1 Test2 Test3 
#> 1 DF64 DF61 DF80 
#> 2 DF63 DF25 DF63 
#> 3 DF89 DF00 DF60 
#> 4 DF30 DF30 DF63 
関連する問題