假设我有一个看起来像这样的数据框:
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的解决方案。
答案 0 :(得分:2)
使用rowSums
mycols <- c("R2", "R3", "R99")
rowSums(df[mycols] != -1) == 0
#[1] FALSE TRUE
这也可以写为
rowSums(df[mycols] == -1) == length(mycols)
#[1] FALSE TRUE
但是,如果您更喜欢dplyr
,则使用rowwise
和do
的一种方法就是
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))