如何避免R循环中POSIXct类型被转换为数值类型
解决POSIXct列在循环赋值后转成数值的问题
你遇到的问题根源很明确:当你用df$prev_hour <- NA初始化列时,这个列的类型是逻辑型(logical),而POSIXct本质是存储为数值的时间戳(从1970-01-01开始的秒数)。当你往逻辑型列里赋值POSIXct对象时,R会自动把整个列强制转换成数值型,导致时间变成了一串数字。
下面给你三种可行的解决方法,按推荐程度排序:
方法1:提前将prev_hour初始化为POSIXct类型的NA
直接把列初始化为POSIXct类型的缺失值,这样后续赋值时就不会触发类型强制转换,也是最直接的解决方案。
修改后的代码:
# Set up dataframe df <- data.frame( building = c('a','a','a','a','b','b','b'), hour = c(as.POSIXct(c('2019-01-01 15:00:00','2019-01-01 15:00:00','2019-01-01 17:00:00','2019-01-01 18:00:00', '2019-01-01 15:00:00','2019-01-01 16:00:00','2019-01-01 17:00:00'))) ) # 初始化POSIXct类型的NA列 df$prev_hour <- as.POSIXct(NA, origin = "1970-01-01") #Loop to get previous value of 'hour' based on conditions for (i in 2:nrow(df)){ if(df$building[i]==df$building[i-1] & as.integer(df$hour[i]-df$hour[i-1])<2){ df$prev_hour[i] <- df$hour[i-1] # 不用再转as.POSIXct,因为列已经是这个类型了 } } df
运行结果里的prev_hour会保持POSIXct格式:
building hour prev_hour 1 a 2019-01-01 15:00:00 <NA> 2 a 2019-01-01 15:00:00 2019-01-01 15:00:00 3 a 2019-01-01 17:00:00 <NA> 4 a 2019-01-01 18:00:00 2019-01-01 17:00:00 5 b 2019-01-01 15:00:00 <NA> 6 b 2019-01-01 16:00:00 2019-01-01 15:00:00 7 b 2019-01-01 17:00:00 2019-01-01 16:00:00
方法2:循环后将数值列转回POSIXct
如果已经生成了数值列,可以手动转回去,但这种方法不如方法1优雅,因为中间经历了不必要的类型转换:
# 循环完成后执行转换 df$prev_hour <- as.POSIXct(df$prev_hour, origin = "1970-01-01")
方法3:用dplyr替代循环(更高效)
对于数据框操作,用tidyverse的dplyr包可以避免手动循环,代码更简洁且性能更好,尤其适合大数据集:
library(dplyr) df <- df %>% group_by(building) %>% mutate( time_diff = as.integer(hour - lag(hour)), prev_hour = ifelse(time_diff < 2 & !is.na(time_diff), lag(hour), NA_POSIXct_) ) %>% select(-time_diff) %>% ungroup()
这里用NA_POSIXct_直接生成POSIXct类型的缺失值,lag()函数直接获取前一行的hour值,完全不用写循环。
内容的提问来源于stack exchange,提问作者Gaurav Bansal
相关产品推荐
相关产品推荐

