替换筛选数据框的第二个条目

时间:2017-11-21 15:56:16

标签: r dataframe

我有一个大型数据框,行数超过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的第一个实例相同。

谢谢!

2 个答案:

答案 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_time2010-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)