R 语言中具有多条件的矢量 if 函数

Jesse John 2023年1月30日 2022年5月18日
  1. R 中 if 语句的限制
  2. R 中的向量化 ifelse() 函数
  3. R 中 dplyr 包的 if_else() 函数
  4. 在 R 中的 if_else() 函数中使用多个条件
  5. 结论
R 语言中具有多条件的矢量 if 函数

常见的数据分析任务是基于同一行的其他列使用一个或多个条件创建或更新数据框列。

如果我们尝试使用 if 语句执行此操作,则仅使用第一行来测试条件,并根据该行更新整个列。

使用数据框时,我们需要适用于多行的工具和技术。本文将学习向量化的 if 函数和向量化的 ANDOR 运算符来组合多个条件。

我们将首先创建一个小的数据框来进行说明。

# 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 的长度为一的逻辑向量 ….仅使用第一个元素。

在以下示例中,我们将根据使用另一列的条件创建一列。

# Try to use the if statement.
cond_df$NewCol = if(Col1 == "B"){cond_df$NewCol = "Col1 was B"} else{cond_df$NewCol = "Col1 was not B"}

# View the result.
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() 函数,我们可以使用它来有条件地更新数据框列。

根据文档,此函数 ...返回一个与 test...具有相同形状的值,这使其适合在数据帧上使用。

该函数的语法是:ifelse(test, value_if_true, value_if_false)。下面的代码说明了这个函数的使用。

# Create a new data frame using the same vectors.
vect_df = data.frame(Col1, Col2)

# Use the vectorized ifelse() function.
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() 函数引起的变化是意料之外的。
# Create and view a vector of dates.
datevec = seq(from = as.Date("2022-01-01"), to = as.Date("2022-01-05"), by = "day")
datevec
class(datevec)

# Create a new vector of dates using the ifelse() function on the previous vector. View it.
mod_datevec = ifelse(datevec < as.Date("2022-01-03"), datevec, as.Date("2022-02-01"))
mod_datevec # Not expected result.
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_truevalue_if_false 属于同一类型。
  • 它从 value_if_true 获取所有其他属性。

让我们以这个函数为例。

# First load the dplyr package.
library(dplyr)

# Create another data frame from the two vectors.
dplyr_df = data.frame(Col1, Col2)

# Use the vectorized if_else() function.
dplyr_df$NewCol = if_else(Col1 == "B", "Col1 was B", "F")

# view the result.
dplyr_df

我们可以检查输出并查看函数是否按预期工作,就像基本 R 的 ifelse()

它在日期上是如何工作的呢?让我们来检查一下。

# Create a new vector using if_else() based on the vector created earlier. View it.
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

我们发现 dplyrif_else() 函数在日期上正常工作。

在 R 中的 if_else() 函数中使用多个条件

我们可以使用向量化的&|组合多个条件运算符,代表 ANDOR

这些可以在 ifelse()if_else() 中使用。在我们的示例中,我们将使用 if_else(),因为它更好。

# Create a data frame from the same two vectors.
mult_df = data.frame(Col1, Col2)

# Create a new column based on multiple conditions combined with AND, using &.
mult_df$AND_Col = if_else((Col1 == "A" & Col2 == "y"), "AND", "F")

# View the data frame with the added column.
mult_df

# Create another column based on multiple conditions combined with Or, using |.
mult_df$OR_Col = if_else((Col1 == "A" | Col2 == "y"), "OR", "F")

# View the data frame with the added column.
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 具有向量化和非向量化版本的 ANDOR 运算符。我们使用了向量化的&|运算符来组合两个条件,因为我们想测试每一行的条件。

&|被矢量化; &&||是非矢量化的。

参考资料和帮助:

在 R Studio 中,有关 if 语句、ifelse() 函数或 if_else() 函数的更多信息,请单击 Help > Search R Help 并在搜索框中键入不带括号的语句/函数名称。

或者,在 R 控制台的命令提示符处键入一个问号,后跟语句/函数名称。

结论

使用单个变量的语句、函数和运算符可能不适用于数据框。我们需要使用适当的工具来完成任务。

为了有条件地创建/更新数据框的列,我们使用了向量化的 ifelse() 函数及其更好的 dplyr 版本 if_else()

我们使用向量化的 ANDOR 运算符来组合多个条件&|

Author: Jesse John
Jesse John avatar Jesse John avatar

Jesse is passionate about data analysis and visualization. He uses the R statistical programming language for all aspects of his work.