R:在多列上进行变异以创建新列

时间:2017-11-23 23:32:10

标签: r loops dplyr mutate

我正在尝试根据其他列的值创建新列。

这是一个类似于我正在处理的数据集。 我有三个变量,Test1,Test2,Test3。 我正在尝试创建一个新变量,如果有任何Test变量,则该变量为1 DF60,DF61,DF63或DF64,否则为0。

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语句,我正在寻找可以的代码 循环遍历多个Test变量,同时允许查找多个值。

在查看了一些类似的主题之后,我尝试了mutate_at,但我认为这不是正确的方法。

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

非常感谢任何帮助!

谢谢!

2 个答案:

答案 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要好得多。然后问题变成在选择的列上进行mutate的rowums。不知道接下来的事情是否是最佳做法,但是它有效(在我之前的一个问题上重新回答了问题: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

答案 1 :(得分:1)

虽然Dries的回答非常好,但我要补充一些关于funs()的解释。

funs()采用成对的后缀和表达式。例如,如果您指定suffix1suffix2,则会获得名为Test1_suffix1Test1_suffix2Test2_suffix1Test2_suffix2的新列,依此类推:

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

其次,您需要.来表示列向量。因此,ifelse(...)的正确版本应该是:

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%优于|的序列。

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