R 中 mutate() 和 filter() 的按行逻辑运算
Rowwise logical operations with mutate() and filter() in R
我经常需要在数据框中 mutate()
或 select()
,条件适用于变量的子集,但我不能始终如一地做到这一点。
玩具示例数据框:
data<-data.frame(id=c("John", "Jane", "Louis", "Mirian"),
a=c(FALSE, FALSE, TRUE, TRUE),
b=c(FALSE, NA, TRUE, NA),
c=c(TRUE, FALSE, TRUE, TRUE),
num=1:4)
操作 1:mutate() 对逻辑变量进行按行操作:
-我想创建一个新列“abc_any”,当 a:c 中的任何一个为 TRUE 时具有 TRUE 值:
我通常使用:
data%>%mutate(abc_any=a|b|c)
id a b c num abc_any
1 John FALSE FALSE TRUE 1 TRUE
2 Jane FALSE NA FALSE 2 NA
3 Louis TRUE TRUE TRUE 3 TRUE
4 Mirian TRUE NA TRUE 4 TRUE
但如果不在链式“|”中指定所有变量 a:c,我就无法做到这一点比较。
我尝试了以下方法,结果不一致。不知道为什么:
data%>%mutate(abc_any=Reduce("|", a:c))
id a b c num abc_any
1 John FALSE FALSE TRUE 1 TRUE
2 Jane FALSE NA FALSE 2 TRUE
3 Louis TRUE TRUE TRUE 3 TRUE
4 Mirian TRUE NA TRUE 4 TRUE
这有效,但令人惊讶的是将 abc_any 强制转换为数字:
data%>%rowwise()%>%mutate(abc_any=Reduce("|", a:c))
# A tibble: 4 x 6
# Rowwise:
id a b c num abc_any
<fct> <lgl> <lgl> <lgl> <int> <int>
1 John FALSE FALSE TRUE 1 1
2 Jane FALSE NA FALSE 2 0
3 Louis TRUE TRUE TRUE 3 1
4 Mirian TRUE NA TRUE 4 1
这不起作用,并抛出几条错误消息:
data%>%rowwise()%>%mutate(abc_any=apply(a:c, 1, any))
操作#2:过滤器()
-我有时想用类似的条件过滤,但不能:
data%>%filter(a|b|c)
工作正常
这个和几个变体(rowwise()%>%Reduce(...)
和其他)失败并出现各种错误消息:
data%>%filter(rowwise(Reduce("|", a:c)))
这个根本没有过滤,抛出“数值表达式有4个元素:只用到第一个”信息:
data%>%filter(Reduce("|", a:c))
我是否必须如上所述使用 mutate() 创建一个新的 'temp' 列,然后进行过滤?
带二进制数值变量:
-现在假设这些逻辑变量被强制转换为数字 data_2<-data%>%mutate(across(where(is.logical), as.numeric))
:
我尝试使用 rowSums()
,但也失败了:
data_2%>%rowwise()%>%mutate(abc_any=rowSums(a:c, na.rm = TRUE))
Error: Problem with `mutate()` input `abc_any`.
x 'x' must be an array of at least two dimensions
ℹ Input `abc_any` is `rowSums(a:c, na.rm = TRUE)`.
ℹ The error occured in row 1.
这些错误有哪些可能的解决方法?
Reduce
应该在 list
- select
列 a:c
上并在其上使用 Reduce
因为 data.frame/tibble
是list
还有
library(dplyr)
data %>%
mutate(abc_any = Reduce("|", select(., a:c)))
或者如果我们需要 filter
data %>%
filter(Reduce(`|`, select(., a:c)))
或者另一种选择是 if_any
data %>%
filter(if_any(a:c))
# id a b c num
#1 John FALSE FALSE TRUE 1
#2 Louis TRUE TRUE TRUE 3
#3 Mirian TRUE NA TRUE 4
或使用 reduce
来自 purrr
library(purrr)
data %>%
mutate(abc_any = select(., a:c) %>%
reduce(`|`))
或带有rowSums
的代码
data %>%
mutate(across(where(is.logical), as.numeric)) %>%
mutate(abc_any = rowSums(select(., a:c), na.rm = TRUE) > 0)
我经常需要在数据框中 mutate()
或 select()
,条件适用于变量的子集,但我不能始终如一地做到这一点。
玩具示例数据框:
data<-data.frame(id=c("John", "Jane", "Louis", "Mirian"),
a=c(FALSE, FALSE, TRUE, TRUE),
b=c(FALSE, NA, TRUE, NA),
c=c(TRUE, FALSE, TRUE, TRUE),
num=1:4)
操作 1:mutate() 对逻辑变量进行按行操作:
-我想创建一个新列“abc_any”,当 a:c 中的任何一个为 TRUE 时具有 TRUE 值:
我通常使用:
data%>%mutate(abc_any=a|b|c)
id a b c num abc_any
1 John FALSE FALSE TRUE 1 TRUE
2 Jane FALSE NA FALSE 2 NA
3 Louis TRUE TRUE TRUE 3 TRUE
4 Mirian TRUE NA TRUE 4 TRUE
但如果不在链式“|”中指定所有变量 a:c,我就无法做到这一点比较。
我尝试了以下方法,结果不一致。不知道为什么:
data%>%mutate(abc_any=Reduce("|", a:c))
id a b c num abc_any
1 John FALSE FALSE TRUE 1 TRUE
2 Jane FALSE NA FALSE 2 TRUE
3 Louis TRUE TRUE TRUE 3 TRUE
4 Mirian TRUE NA TRUE 4 TRUE
这有效,但令人惊讶的是将 abc_any 强制转换为数字:
data%>%rowwise()%>%mutate(abc_any=Reduce("|", a:c))
# A tibble: 4 x 6
# Rowwise:
id a b c num abc_any
<fct> <lgl> <lgl> <lgl> <int> <int>
1 John FALSE FALSE TRUE 1 1
2 Jane FALSE NA FALSE 2 0
3 Louis TRUE TRUE TRUE 3 1
4 Mirian TRUE NA TRUE 4 1
这不起作用,并抛出几条错误消息:
data%>%rowwise()%>%mutate(abc_any=apply(a:c, 1, any))
操作#2:过滤器()
-我有时想用类似的条件过滤,但不能:
data%>%filter(a|b|c)
工作正常
这个和几个变体(rowwise()%>%Reduce(...)
和其他)失败并出现各种错误消息:
data%>%filter(rowwise(Reduce("|", a:c)))
这个根本没有过滤,抛出“数值表达式有4个元素:只用到第一个”信息:
data%>%filter(Reduce("|", a:c))
我是否必须如上所述使用 mutate() 创建一个新的 'temp' 列,然后进行过滤?
带二进制数值变量:
-现在假设这些逻辑变量被强制转换为数字 data_2<-data%>%mutate(across(where(is.logical), as.numeric))
:
我尝试使用 rowSums()
,但也失败了:
data_2%>%rowwise()%>%mutate(abc_any=rowSums(a:c, na.rm = TRUE))
Error: Problem with `mutate()` input `abc_any`.
x 'x' must be an array of at least two dimensions
ℹ Input `abc_any` is `rowSums(a:c, na.rm = TRUE)`.
ℹ The error occured in row 1.
这些错误有哪些可能的解决方法?
Reduce
应该在 list
- select
列 a:c
上并在其上使用 Reduce
因为 data.frame/tibble
是list
还有
library(dplyr)
data %>%
mutate(abc_any = Reduce("|", select(., a:c)))
或者如果我们需要 filter
data %>%
filter(Reduce(`|`, select(., a:c)))
或者另一种选择是 if_any
data %>%
filter(if_any(a:c))
# id a b c num
#1 John FALSE FALSE TRUE 1
#2 Louis TRUE TRUE TRUE 3
#3 Mirian TRUE NA TRUE 4
或使用 reduce
来自 purrr
library(purrr)
data %>%
mutate(abc_any = select(., a:c) %>%
reduce(`|`))
或带有rowSums
data %>%
mutate(across(where(is.logical), as.numeric)) %>%
mutate(abc_any = rowSums(select(., a:c), na.rm = TRUE) > 0)