在dplyr::mutate中提取POSIXct时间小时并忽略缺失值
解决POSIXct类型列提取小时时的NA值报错问题
问题场景
有包含id和datetime(POSIXct类型,含NA值)的tibble数据,提取datetime中的小时生成新列时因缺失值报错,使用dplyr::if_else处理NA时出现Result must be length 1, not 0错误。
示例数据
library(tibble) df <- tibble( id = 1:3, datetime = as.POSIXct(c("2024-05-20 08:30:00", "2024-05-20 14:15:00", NA)) )
错误代码示例
# 触发报错的代码 library(dplyr) df %>% mutate(hour = if_else(is.na(datetime), NA, as.integer(strftime(datetime, "%H"))))
解决方案
方案1:使用lubridate包的hour()函数(推荐)
lubridate的hour()函数原生支持POSIXct类型的NA值,无需额外条件判断,直接返回对应小时或NA:
library(lubridate) library(dplyr) df_processed <- df %>% mutate(hour = hour(datetime)) # 输出结果 df_processed
输出:
# A tibble: 3 × 3 id datetime hour <int> <dttm> <int> 1 1 2024-05-20 08:30:00 8 2 2 2024-05-20 14:15:00 14 3 3 NA NA
方案2:修正dplyr::if_else的类型匹配
dplyr::if_else要求分支返回值的类型、长度严格一致,需将NA指定为整数类型(NA_integer_):
library(dplyr) df_processed <- df %>% mutate(hour = if_else(is.na(datetime), NA_integer_, hour(datetime)))
方案3:使用base R的format()+ifelse
base R的ifelse对类型要求更宽松,也可直接用format()处理(NA值会自动转为NA_integer_):
df_processed <- df %>% mutate(hour = as.integer(format(datetime, "%H")))
错误原因说明
dplyr::if_else的严格类型检查机制导致:当你传入NA(默认逻辑型)和整数型的小时值时,类型不匹配,触发内部长度校验错误。指定NA_integer_可保证分支类型一致;而lubridate::hour()直接处理POSIXct类型,原生兼容NA,从根源避免了类型问题。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

