dplyr基于向量中的列进行突变

时间:2018-12-19 02:42:16

标签: r dplyr mutate

假设我有一个看起来像这样的数据框:

R1 R2 R3 ... R99 R100
-1 -1  2 ...   3   57
45 -1 -1 ...  -1   37

我想创建一个实现以下逻辑的新列:如果mycols中指定的列中的所有值都等于-1,则TRUE,否则为{{1 }}。因此,如果我设置FALSE,那么结果将是

mycols <- c("R2", "R3", "R99")

另一方面,如果我设置somefeature FALSE TRUE ,那么结果将是

mycols <- c("R1", "R2")

对于一般的somefeature TRUE FALSE ,该怎么做?我更喜欢使用dplyr的解决方案。另外,我希望能够在手术后保留所有列。


更新:要决定接受哪种解决方案,我决定比较所有方法的性能:

mycols

基本R解决方案是最快的。但是,我确实指定了我想使用tidyverse,因此我决定接受提供最快的基于tidyverse的解决方案。

2 个答案:

答案 0 :(得分:2)

使用rowSums

的快速基础R解决方案
mycols <- c("R2", "R3", "R99")

rowSums(df[mycols] != -1) == 0
#[1] FALSE  TRUE

这也可以写为

rowSums(df[mycols] == -1) == length(mycols)
#[1] FALSE  TRUE

但是,如果您更喜欢dplyr,则使用rowwisedo的一种方法就是

library(dplyr)


bind_cols(df, somefeature = df %>%
                             select(mycols) %>%
                             rowwise() %>%
                             do( (.) %>% as.data.frame %>% 
                             mutate(temp = all(. == -1))) %>%
                             pull(temp))


#  R1 R2 R3 R99 R100 somefeature
#1 -1 21  2   3   57       FALSE
#2 45 -1 -1  -1   37        TRUE

答案 1 :(得分:1)

这里是tidyverse的一个选项。创建一个函数以供重复使用。使用map(来自purrr)循环遍历'nameVec'中指定的列子集,创建list逻辑向量,reduce通过求和将其转换为单个向量并检查它是否等于'nameVec'的length

library(tidyverse)
mycols <- c("R2", "R3", "R99")
f1 <- function(dat, nameVec){
 dat %>%
    mutate(somefeature = map(.[nameVec], `==`, -1) %>% 
                                  reduce(`+`) %>%
                      {. == length(nameVec) })

 }


f1(df1, mycols)
#   R1 R2 R3 R99 R100 somefeature
#1 -1 -1  2   3   57       FALSE
#2 45 -1 -1  -1   37        TRUE

mycols <- c("R1", "R2")
f1(df1, mycols)
#    R1 R2 R3 R99 R100 somefeature
#1 -1 -1  2   3   57        TRUE
#2 45 -1 -1  -1   37       FALSE

数据

df1 <- structure(list(R1 = c(-1L, 45L), R2 = c(-1L, -1L), R3 = c(2L, 
 -1L), R99 = c(3L, -1L), R100 = c(57L, 37L)), class = "data.frame", 
 row.names = c(NA, -2L))