R语言日期数字加前缀报错:missing value where TRUE/FALSE needed
问题排查与解决方案
报错信息
Error in if (as.numeric(spotify$rel_date[i]) > 22) { :
missing value where TRUE/FALSE needed
问题背景
Spotify发布日期格式为dd-mmm-yy/mmm-yy/yyyy,需求是提取年份的最后两位数字,根据数值添加19、20或200前缀以标准化年份格式。其中extractDate函数可正常返回两位数字格式结果,但getYears函数及后续循环处理出现上述报错。
用户原代码
The spotify release dates are either formatted as dd-mmm-yy / mmm-yy / yyyy ## To standardize the years, extract the last two numbers and add 19 or 20 to prefix ##' extractDate function ##' @string is the Date in string format to extract the year from ##' @n is the number of characters to extract from the string ##' substr(x, start, stop) from RDocumentation extractDate = function(string, n){ extract =substr(string, nchar(string)-n+1, nchar(string)) } ##' getYears function ##' @string is the Date in string format to add onto to make a proper year ##' For any numbers "##" greater than 22, we will attach "19" in the prefix (i.e.: "1967") ##' For any numbers "##" less or equal to 22, we will attach "20" in the prefix (i.e: "2006") getYears = function(string){ if (as.numeric(string)>22){ string=paste0("19",string) } else { string=paste0("20",string) } } ## spoti$rel_date=extractDate(spoti$rel_date,2) spotify$rel_date=extractDate(spotify$rel_date,2) spotify$rel_date for (i in spotify$rel_date){ if (as.numeric(spotify$rel_date[i])>22){ spotify$rel_date[i]=paste0("19",spotify$rel_date[i]) } else if (as.numeric(spotify$rel_date[i]<10)){ spotify$rel_date[i]=paste0("200",spotify$rel_date[i]) } else { spotify$rel_date[i]=paste0("20",spotify$rel_date[i]) } }
问题原因
- 循环索引错误:
for (i in spotify$rel_date)中i是rel_date的取值而非索引,用spotify$rel_date[i]会把年份值当作索引,导致取到不存在的元素或NA。 - 括号位置错误:
as.numeric(spotify$rel_date[i]<10)逻辑错误,应该先转数值再比较,即as.numeric(spotify$rel_date[i]) <10。 - 未处理NA值:当
rel_date存在NA时,as.numeric()会返回NA,if条件无法识别NA,直接报错。 getYears函数逻辑不全:未覆盖单数字年份(需加200前缀)的场景,也未处理NA。
修复方案
方案1:修正原循环逻辑
# 先提取年份最后两位 spotify$rel_date <- extractDate(spotify$rel_date, 2) # 按索引遍历,处理每个元素 for (i in seq_along(spotify$rel_date)) { year_part <- as.numeric(spotify$rel_date[i]) # 跳过NA值,或根据需求赋值 if (is.na(year_part)) next if (year_part > 22) { spotify$rel_date[i] <- paste0("19", spotify$rel_date[i]) } else if (year_part < 10) { spotify$rel_date[i] <- paste0("200", spotify$rel_date[i]) } else { spotify$rel_date[i] <- paste0("20", spotify$rel_date[i]) } }
方案2:优化getYears函数+向量式操作
# 完善getYears函数,加入NA处理和单数字逻辑 getYears = function(string){ year_num <- as.numeric(string) if (is.na(year_num)) { return(string) # 保留原NA或自定义返回值 } if (year_num > 22){ paste0("19", string) } else if (year_num < 10){ paste0("200", string) } else { paste0("20", string) } } # 提取年份后直接用sapply批量处理,无需循环 spotify$rel_date <- extractDate(spotify$rel_date, 2) spotify$rel_date <- sapply(spotify$rel_date, getYears)
方案3:用dplyr实现更简洁的向量式处理
library(dplyr) # 提取年份最后两位 spotify$rel_date <- extractDate(spotify$rel_date, 2) # 用case_when统一处理所有情况 spotify$rel_date <- case_when( as.numeric(rel_date) > 22 ~ paste0("19", rel_date), as.numeric(rel_date) < 10 ~ paste0("200", rel_date), !is.na(as.numeric(rel_date)) ~ paste0("20", rel_date), TRUE ~ rel_date # 处理NA或非数值的原始值 )
内容的提问来源于stack exchange,提问作者Melody
相关产品推荐
相关产品推荐

