R使用fifelse转换月份时month.abb负下标报错如何解决
问题解决:数字转月份缩写时负下标报错的规避方案
你的报错推测完全正确:data.table的fifelse为了保证运行效率,会先完整计算两个分支的所有值,再根据条件选择对应分支的结果,因此当registration_month<=12时,否分支的registration_month-12会生成0或负数,作为month.abb的下标直接触发报错。
可行解决方案
方案1:先统一计算有效月份下标,再拼接前缀(最推荐,性能最优)
利用取模运算将任意月份数统一转换为1-12的合法下标,从根源避免负下标问题:
library(data.table) rg <- fread("https://raw.githubusercontent.com/joyce-john/mastering-product-analytics/main/registrations.csv") rg[, `:=`( # 先计算1-12区间的合法月份下标 mon_idx = (registration_month - 1) %% 12 + 1, # 再根据年份判断是否加前缀 month_rg2 = fifelse(registration_month <= 12, month.abb[mon_idx], paste0("2nd Year ", month.abb[mon_idx])) )][, mon_idx := NULL] # 删除临时索引列
方案2:分条件赋值,避免同时计算两个分支
按照条件分两次对不同行赋值,永远只会计算当前符合条件的行的表达式,不会触发非法下标问题:
rg[, month_rg2 := NA_character_] # 先处理12个月以内的记录 rg[registration_month <= 12, month_rg2 := month.abb[registration_month]] # 再处理超过12个月的记录 rg[registration_month > 12, month_rg2 := paste0("2nd Year ", month.abb[registration_month - 12])]
方案3:给否分支的下标加兜底,避免非法值
如果想保留原有的fifelse写法,只需要给否分支的下标加一层合法值兜底,保证计算时不会出现负数即可。不符合条件的行不会使用否分支的计算结果,因此不影响最终输出:
rg[,.(month_rg2 = fifelse(registration_month<= 12, month.abb[registration_month], # 用pmax把下标最小限制为1,避免负下标报错 paste0("2nd Year ", month.abb[pmax(1, registration_month-12)])))]
内容的提问来源于stack exchange,提问作者Li Deborah Jia
相关产品推荐
相关产品推荐

