首页 > 解决方案 > 对值进行操作时如何忽略空单元格或 NA

问题描述

我正在尝试计算数据框中两个日期之间的工作日数。

我正在使用这里给出的解决方案。当所有列中的日期都可用时,该解决方案有效,但如果缺少任何日期,则没有结果。

这是正在使用的代码:

library(dplyr)

# The macro to calculate working days
Nweekdays <- Vectorize(function(a, b)
  sum(!weekdays(seq(a, b, "days")) %in% c("Saturday", "Sunday")))

# Sample data frame
id = c("ID1", "ID2", "ID3") 
startDate = c("2019-08-01", "2019-08-06", "2019-08-10") 
endDate = c("2019-08-05", "2019-08-15", "2019-08-20")
df = data.frame(id, startDate, endDate)

# Using dplyr to coerce to Date and run macro
df <- df %>%
  mutate(startDate = as.Date(startDate)) %>% 
  mutate(endDate = as.Date(endDate)) %>% 
  mutate(workingdays = Nweekdays(startDate, endDate))

该代码正常工作,并为我提供了一个包含工作日的新专栏。但如果其中一个日期缺失或不适用,例如

startDate = c("2019-08-01", "", "2019-08-10")

然后我得到

Evaluation error: 'to' must be a finite number.

并且没有生成新列。我想要缺失值的空结果,但所有其他值的正确结果。我敢肯定我错过了一些基本的东西,所以为此道歉!

标签: rdplyr

解决方案


您只需要更新您的函数以处理非日期值,因此它只尝试计算 a 和 b 是否都是日期:

Nweekdays <- Vectorize(function(a, b) {
  if (!is.na(a) & !is.na(b)) {
    sum(!weekdays(seq(a, b, "days")) %in% c("Saturday", "Sunday"))
  } else {
    return(NA)
  }
})

您可以使用一些更严格的验证形式,而不是!is.na()使用类似lubridate::is.Date()的方法,但这是一个基本解决方案,当您as.Date()在 mutate 行中调用时,任何非日期值都将转换为 NA。


推荐阅读