我有一个大型数据框,行数超过18米,格式如下:
house_id date_time value
1000 2010-10-31 00:30:00 0.6
1000 2010-10-31 00:30:00 0.4
1000 2010-10-31 01:00:00 0.5
1001 2010-10-31 00:30:00 0.5
1001 2010-10-31 00:30:00 0.7
1001 2010-10-31 01:00:00 0.9
我想将date_time = 2010-10-31 00:30:00
替换为包含house_id
的第二行2010-10-31 01:00:00
,但保持2010-10-31 00:30:00
的第一个实例相同。
谢谢!
答案 0 :(得分:2)
OP要求为每个house_id
替换特定日期时间值的第二次(最后一次)出现。
根据OP,has数据集有超过18 M行,这使得值得考虑更新到位,即不复制完整的数据对象。
library(data.table)
setDT(DF) # coerce to data.table in place
address(DF)
DF[DF[date_time == as.POSIXct("2010-10-31 00:30:00"), last(.I), by = house_id]$V1,
date_time := as.POSIXct("2010-10-31 01:00:00")][]
address(DF)
要更新的行由
标识DF[date_time == as.POSIXct("2010-10-31 00:30:00"), last(.I), by = house_id]
house_id V1 1: 1000 2 2: 1001 5
在更新操作之前和之后对address(DF)
的调用是验证DF
是否已被修改而不进行复制。
作为更新所选行的替代方法,可以使用连接期间的更新:
library(data.table)
setDT(DF)
address(DF)
DF[CJ(unique(house_id), as.POSIXct("2010-10-31 00:30:00")),
on = .(house_id = V1, date_time = V2), mult = "last",
date_time := as.POSIXct("2010-10-31 01:00:00")][]
address(DF)
返回相同的结果:
house_id date_time value 1: 1000 2010-10-31 00:30:00 0.6 2: 1000 2010-10-31 01:00:00 0.4 3: 1000 2010-10-31 01:00:00 0.5 4: 1001 2010-10-31 00:30:00 0.5 5: 1001 2010-10-31 01:00:00 0.7 6: 1001 2010-10-31 01:00:00 0.9
此处,CJ()
创建一个查找表,其中包含所有唯一house_id
和要替换的日期时间。
问题的措辞表明每个house_id
的总是 2行,日期时间as.POSIXct("2010-10-31 00:30:00")
。
这可以通过
进行验证DF[date_time == as.POSIXct("2010-10-31 00:30:00"), .N, by = house_id][N != 2]
应该返回一个空的data.table。
答案 1 :(得分:1)
使用dplyr
的解决方案。我们的想法是按house_id
对数据进行分组,然后检查date_time
是2010-10-31 00:30:00
,行号是ifelse
的2。如果TRUE
,请将该值替换为2010-10-31 01:00:00
。
library(dplyr)
dt2 <- dt %>%
group_by(house_id) %>%
mutate(date_time = ifelse(date_time %in% "2010-10-31 00:30:00" &
row_number() == 2, "2010-10-31 01:00:00",
date_time)) %>%
ungroup()
dt2
# # A tibble: 6 x 3
# house_id date_time value
# <int> <chr> <dbl>
# 1 1000 2010-10-31 00:30:00 0.6
# 2 1000 2010-10-31 01:00:00 0.4
# 3 1000 2010-10-31 01:00:00 0.5
# 4 1001 2010-10-31 00:30:00 0.5
# 5 1001 2010-10-31 01:00:00 0.7
# 6 1001 2010-10-31 01:00:00 0.9
数据强>
dt <- read.table(text = "house_id date_time value
1000 '2010-10-31 00:30:00' 0.6
1000 '2010-10-31 00:30:00' 0.4
1000 '2010-10-31 01:00:00' 0.5
1001 '2010-10-31 00:30:00' 0.5
1001 '2010-10-31 00:30:00' 0.7
1001 '2010-10-31 01:00:00' 0.9",
header = TRUE, stringsAsFactors = FALSE)