R 中具有多个条件的函数向量化
一项常见的数据分析任务是根据同一行的其他列使用一个或多个条件创建或更新数据框列。
如果我们尝试使用 if 语句来执行此操作,则只会使用第一行来测试条件,并且会根据该行更新整列。
在处理数据框时,我们需要适用于多行的工具和技术。 本文将学习矢量化 if 函数和矢量化 AND 和 OR 运算符以组合多个条件。
我们将首先创建一个小数据框用于说明。
# Create two vectors.
Col1 = rep(c("A", "B"), times = 2, each = 2)
Col2 = rep(c("x", "y"), times = 1, each = 4)
# Create a data frame.
cond_df = data.frame(Col1, Col2)
# View the data frame.
cond_df
R 中 if 语句的限制
根据文档,if 语句采用非 NA 的长度为一的逻辑向量……仅使用第一个元素。
在以下示例中,我们将根据使用另一列的条件创建一列。
# 尝试使用if语句
cond_df$NewCol = if(Col1 == "B"){cond_df$NewCol = "Col1 was B"} else{cond_df$NewCol = "Col1 was not B"}
# 查看结果
cond_df
输出结果
Col1 Col2 NewCol
1 A x Col1 was not B
2 A x Col1 was not B
3 B x Col1 was not B
4 B x Col1 was not B
5 A y Col1 was not B
6 A y Col1 was not B
7 B y Col1 was not B
8 B y Col1 was not B
当我们执行此 if 语句但创建列时,R 发出警告。 结果不是我们想要的。
仅评估第一行,并将结果应用于所有数据框行。
R 中的矢量化 ifelse() 函数
Base R 包含一个向量化的 ifelse() 函数,我们可以使用它有条件地更新数据框列。
根据文档,此函数“……返回一个与测试形状相同的值……”,这使其适合在数据框上使用。
该函数的语法是:ifelse(test, value_if_true, value_if_false)
。 下面的代码说明了这个函数的用法。
# 使用相同的向量创建一个新的数据框。
vect_df = data.frame(Col1, Col2)
# 使用向量化的 ifelse() 函数。
vect_df$NewCol = ifelse(Col1 == "B", "Col1 was B", "F")
# view the result.
vect_df
输出结果
> vect_df
Col1 Col2 NewCol
1 A x F
2 A x F
3 B x Col1 was B
4 B x Col1 was B
5 A y F
6 A y F
7 B y Col1 was B
8 B y Col1 was B
此函数按照预期执行。 我们可以使用它根据其他列的值使用条件来创建或更新数据框列。
但是这个功能有一个限制。 文档说明 ifelse()
剥离属性。 这在处理日期和因素时很重要。
让我们看一个问题的例子,它们是:
- 创建一个日期向量。
-
在第一个向量上使用
ifelse()
函数创建一个新向量。ifelse()
函数引起的更改是意外的。
# 创建和查看日期向量。
datevec = seq(from = as.Date("2022-01-01"), to = as.Date("2022-01-05"), by = "day")
datevec
class(datevec)
# 在前一个向量上使用 ifelse() 函数创建一个新的日期向量。 查看它。
mod_datevec = ifelse(datevec < as.Date("2022-01-03"), datevec, as.Date("2022-02-01"))
mod_datevec # 不是预期的结果.
class(mod_datevec) # Not date.
输出结果
> datevec = seq(from = as.Date("2022-01-01"), to = as.Date("2022-01-05"), by = "day")
> datevec
[1] "2022-01-01" "2022-01-02" "2022-01-03" "2022-01-04" "2022-01-05"
> class(datevec)
[1] "Date"
>
> mod_datevec = ifelse(datevec < as.Date("2022-01-03"), datevec, as.Date("2022-02-01"))
> mod_datevec
[1] 18993 18994 19024 19024 19024
> class(mod_datevec)
[1] "numeric"
我们发现日期已经变成了数字。 ifelse()
函数在日期和因子变量上无法按预期工作。
现在让我们看看 dplyr 包提供的解决方案。
R中dplyr包的 if_else()
函数
dplyr 包中的 if_else()
函数解决了一些与基础 R 的 ifelse() 函数相关的问题。
-
它确保
value_if_true
和value_if_false
是同一类型。 -
它从
value_if_true
中获取所有其他属性。
让我们以这个函数为例。
# 首先加载 dplyr 包。
library(dplyr)
# 从这两个向量创建另一个数据框。
dplyr_df = data.frame(Col1, Col2)
# U使用向量化的 if_else() 函数。
dplyr_df$NewCol = if_else(Col1 == "B", "Col1 was B", "F")
# 查看结果
dplyr_df
我们可以检查输出并看到该函数按预期工作,就像 base R 的 ifelse()
一样。
它如何在日期上工作? 让我们检查一下。
# 基于先前创建的向量,使用 if_else() 创建一个新向量。 查看它。
dplyr_datevec = if_else(datevec < as.Date("2022-01-03"), datevec, as.Date(NA))
dplyr_datevec
输出结果
> dplyr_datevec = if_else(datevec < as.Date("2022-01-03"), datevec, as.Date(NA))
> dplyr_datevec
[1] "2022-01-01" "2022-01-02" NA NA NA
我们发现 dplyr 和 if_else()
函数在日期上可以正常工作。
在 R 中的 if_else() 函数中使用多个条件
我们可以使用向量化的 &
和 |
组合多个条件 运算符,代表 AND 和 OR。
这些可以在 ifelse()
和 if_else()
中使用。 在我们的示例中,我们将使用 if_else()
因为它更好。
# 从相同的两个向量创建数据框。
mult_df = data.frame(Col1, Col2)
# 基于多个条件结合AND创建新列,使用&。
mult_df$AND_Col = if_else((Col1 == "A" & Col2 == "y"), "AND", "F")
# 查看包含添加列的数据框。
mult_df
# 根据多个条件结合 Or 创建另一列,使用 |。
mult_df$OR_Col = if_else((Col1 == "A" | Col2 == "y"), "OR", "F")
# 查看包含添加列的数据框。
mult_df
最后一条命令的输出:
> mult_df
Col1 Col2 AND_Col OR_Col
1 A x F OR
2 A x F OR
3 B x F F
4 B x F F
5 A y AND OR
6 A y AND OR
7 B y F OR
8 B y F OR
请记住,R 具有 AND 和 OR 运算符的矢量化和非矢量化版本。 我们使用矢量化的 &
和 |
运算符来组合两个条件,因为我们想测试每一行的条件。
&
和 |
被矢量化; &&
和 ||
是非矢量化的。
参考和帮助:
在 R Studio 中,有关 if 语句、ifelse() 函数或 if_else() 函数的更多信息,请单击“帮助”>“搜索 R 帮助”,然后在搜索框中键入语句/函数名称(不带括号)。
或者,在 R 控制台的命令提示符处键入一个问号,后跟语句/函数名称。
结论
使用单个变量的语句、函数和运算符可能不适用于数据框。 我们需要为任务使用合适的工具。
为了有条件地创建/更新数据框的列,我们使用了向量化的 ifelse()
函数及其更好的 dplyr 版本 if_else()
。
我们使用向量化的 AND 和 OR 运算符来组合多个条件,&
和 |
。
相关文章
Oracle 的 decode 函数在 MySQL 中的等价物
发布时间:2023/05/09 浏览次数:115 分类:MySQL
-
本篇文章介绍了三种替代实现,我们可以将它们用作 MySQL 中 Oracle 的 decode() 函数的等价物。 为此,我们将使用 IF()、CASE 以及 FIELD() 和 ELT() 的组合。
MySQL 中 Zerofill 的使用、优势和替代方案
发布时间:2023/05/09 浏览次数:144 分类:MySQL
-
在本文中我们将了解 MySQL 中 ZEROFILL 属性的使用、优势和替代方案。ZEROFILL 属性在 MySQL 中的使用和好处
在 Ubuntu 中重置 MySQL root 密码
发布时间:2023/05/09 浏览次数:70 分类:MySQL
-
本篇文章介绍了我们需要在 Ubuntu 中重置 MySQL root 密码的两种情况。 第一,当我们忘记了root密码,想要重新设置; 其次,当我们无法使用 mysql_secure_installation 设置 root 密码时。
MySQL Group by With 计数函数
发布时间:2023/05/09 浏览次数:56 分类:MySQL
-
本篇文章将讨论 SQL GROUP BY 子句以及使用 MySQL 的聚合函数。GROUP BY 子句通常与一些聚合函数一起使用,例如 COUNT()、SUM()、MIN()、MAX() 和 AVG()。
在 MySQL 中使用 WHERE 选择多个值
发布时间:2023/05/09 浏览次数:167 分类:MySQL
-
本文是关于使用 MySQL 查询从特定表或关系中获取满足特定条件的数据。 为此,在 SQL 查询中使用 WHERE 子句。
MySQL 修复 Data Is Truncated for a Column 错误
发布时间:2023/05/09 浏览次数:72 分类:MySQL
-
本文介绍 MySQL 错误 Data is truncated for a column 的可能原因和解决方法。修复数据因 MySQL 中的列错误而被截断
MySQL 错误 Error Server PID File Could Not Be Found 解决
发布时间:2023/05/09 浏览次数:98 分类:MySQL
-
在这篇文章中,我们将研究错误! Error Server PID File Could Not Be Found! 在 MySQL 及其解决方案中有充分的解释。
MySQL ForEach 循环
发布时间:2023/05/08 浏览次数:140 分类:MySQL
-
本篇文章介绍如何在一条语句中使用 INSERT、SELECT、WHERE 和 JOIN 模拟 MySQL 中的 foreach 循环。
遍历 MySQL 表的所有行
发布时间:2023/05/08 浏览次数:161 分类:MySQL
-
本篇文章介绍了如何使用 WHILE 和 CURSOR 遍历 MySQL 表的所有行。遍历 MySQL 表的所有行