【问题标题】:R: mutate over multiple columns to create a new columnR:对多个列进行变异以创建一个新列
【发布时间】:2018-05-07 22:50:19
【问题描述】:

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

这是一个与我正在研究的数据集相似的数据集。 我有三个变量,Test1,Test2,Test3。 我正在尝试创建一个新变量,如果有任何测试变量是 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 语句,正在寻找可以 循环多个测试变量,同时允许查找多个值。

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

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

非常感谢任何帮助!

谢谢!

【问题讨论】:

    标签: r loops dplyr


    【解决方案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 会好得多。然后问题就变成了在选择的列上进行行和。不知道接下来的事情是否是最佳实践,但它确实有效(重新编写了我之前问题的答案: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
    

    【讨论】:

    • 谢谢!有没有办法保留所有原始变量(除了Test1,Test2,Test3还有其他变量)?我需要基于相同的 Test1、Test2、Tes3 变量创建多个变量,因此希望不要更改它们。
    • split 根据参数将 df 拆分为 df 列表。以下 map_df 将参数应用于每个 df,并将它们绑定回一个 df。在这种情况下,我不想要一个不同df的列表,而只是一个df(整个df)的列表。这就是为什么我根据一个始终正确的论点进行拆分(不确定是否有必要,您可以尝试不使用。此答案基于我在 stackoverflow 上的上一个问题。如果您点击链接,您将看到拆分的来源)
    【解决方案2】:

    虽然 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
    

    【讨论】:

      猜你喜欢
      • 2022-01-02
      • 1970-01-01
      • 2017-10-24
      • 1970-01-01
      • 1970-01-01
      • 2020-09-21
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多