在数据处理中,我们经常需要根据特定条件对数据进行修改。mutate(across())
函数是 dplyr
包中一个强大的工具,它可以方便地对数据框中的多列进行同时修改。当我们需要根据另一列的值来修改数据时,就需要使用字符串来动态地引用列名,然后利用 ifelse()
函数根据条件进行判断。
本教程将介绍如何结合使用字符串和 ifelse()
函数在 mutate(across())
函数中根据条件动态地修改数据。我们将以一个示例数据为例,演示如何根据 _Direction
列的值来修改数据框中的其他列来源:www.t*e*l*l*m-e-t|h|e|code.com。
示例数据
假设我们有一个包含两列 A
和 B
的数据框,以及与之对应的方向列 A_Direction
和 B_Direction
,分别表示对应列的值是递增还是递减。
library(tidyverse)
colNames <- c('A', 'B')
df <- tibble(A = sample(1:1000, 20),
A_Direction = 'Decreasing',
B = sample(1:1000, 20),
B_Direction = 'Increasing')
我们的目标是:如果 A_Direction
或 B_Direction
为 “Decreasing”,则将对应列的值改为 0,否则改为 1。
尝试方法(不可行)
最直观的思路是直接在 ifelse()
函数的 test
参数中使用字符串拼接的方式来获取 _Direction
列的值,并进行比较。
dfNew <- df %>%
mutate(across(.cols = matches(paste0('^', colNames, '$')),
.fns = ~ifelse(test = paste0(cur_column(), '_Direction')=='Decreasing',
yes = 0,
no = 1)))
然而,这种方法并不生效,因为 ifelse()
函数无法识别字符串类型的参数。
解决方法
我们可以使用以下两种方法来解决这个问题:
1. 使用 get()
函数
get()
函数可以根据字符串来获取变量的值。我们可以使用 get()
函数来获取 _Direction
列的值,并将其与 “Decreasing” 进行比较。
library(dplyr, warn = FALSE)
set.seed(123)
df %>%
mutate(across(
matches(paste0("^", colNames, "$")),
~ +(!get(paste0(cur_column(), "_Direction")) == "Decreasing")
))
解释:
across()
函数用于对数据框中符合条件的列进行修改。matches(paste0("^", colNames, "$"))
用于匹配以colNames
中的元素开头(”^” 表示开头)的列名。~ +(!get(paste0(cur_column(), "_Direction")) == "Decreasing")
是一个匿名函数,它将当前处理的列名与 “_Direction” 拼接,并使用get()
函数获取对应列的值。!
操作符用于取反,如果get()
函数获取到的值不等于 “Decreasing”,则返回TRUE
,否则返回FALSE
。+
操作符用于将逻辑值转换为数值类型,TRUE
转换为 1,FALSE
转换为 0。
2. 使用 pick()
函数
pick()
函数可以根据字符串来获取数据框中的特定列。我们可以使用 pick()
函数来获取 _Direction
列,并将它与 “Decreasing” 进行比较。
df %>%
mutate(across(
matches(paste0("^", colNames, "$")),
~ +(!pick(paste0(cur_column(), "_Direction")) == "Decreasing")[[1]]
))
解释:
pick()
函数类似于get()
函数,但它返回的是一个数据框。[[1]]
用于提取数据框中的第一个元素,即对应_Direction
列的值。
总结
本教程展示了两种使用字符串在 mutate(across())
函数中引用 ifelse()
函数参数的方法,分别利用了 get()
和 pick()
函数。这两种方法都能够解决字符串不能直接在 ifelse()
函数中使用的难题,从而方便我们根据条件动态地修改数据。
希望本教程能够帮助您理解如何在 mutate(across())
函数中使用字符串,并更好地利用 dplyr
包进行数据处理。