R语言lubridate包make_datetime生成日期默认返回公元1年1月1日问题
问题成因
结果异常由两个核心错误导致:
- 你提前将
Month/Day/Year/Time全部转为了因子类型,make_datetime()接收参数时会读取因子的底层整数编码,而非你看到的因子标签值。从你的运行输出可以验证:Month只有1个水平"6",所有行的底层编码都是1Year只有1个水平"2022",所有行的底层编码都是1Day的两个水平为"15""16",对应底层编码1、2Time的三个水平为"700""1200""1600",对应底层编码1、2、3
函数实际拿到的入参为年=1、月=1、日=1、小时=3,自然会输出公元1年1月1日03:00的错误结果。
- 你的
Time列是700、1200、1600这种紧凑格式的24小时时间值,分别代表7点整、12点整、16点整,不能直接作为小时参数传入make_datetime()——函数会把传入值直接当作小时数,700小时显然超出了合法时间范围。
解决方法
不需要修改Excel源文件的时间格式,调整R代码逻辑即可:
- 不要在数据导入阶段就把年、月、日、时间这类需要做计算的列转成因子,先转为数值型用于日期计算。
- 将紧凑格式的时间值拆分为独立的小时、分钟数值,再传入
make_datetime()。 - 如果后续需要用年、月、日列做分组统计,等
Measurement日期列计算完成后再转因子即可。
修正后的可运行代码如下:
Temp.dat <- read_excel("Temperature Data.xlsx", sheet = "Sheet1", na="NA") %>% mutate( Treatment = as.factor(Treatment), TempC = as.factor(TempC), TempF = as.factor(TempF), # 日期时间相关列转数值,若列已经是因子,需写为as.numeric(as.character(列名)) Month = as.numeric(Month), Day = as.numeric(Day), Year = as.numeric(Year), Time = as.numeric(Time), # 拆分紧凑格式时间:除以100取整得小时,取余得分钟 hour = Time %/% 100, minute = Time %% 100 ) %>% select(TempC, Treatment, Month, Day, Year, Time, hour, minute) %>% mutate( Measurement = make_datetime( year = Year, month = Month, day = Day, hour = hour, min = minute ) )
注意:如果日期时间相关列已经被转为因子类型,转数值时必须先转为字符型再转数值,否则会直接读取因子的底层整数编码,再次触发计算错误。
内容的提问来源于stack exchange,提问作者Joe Ballenger
相关产品推荐
相关产品推荐

