ř更换NA与另一列值的组内的下一个值值

问题描述:

我有一个数据帧,如下ř更换NA与另一列值的组内的下一个值值

tmpdf <- data.frame(spaceNum=c(1,1,1,2,2,2,2), time.IN=c("2015-09-04 16:30", "2015-09-04 19:50", "2015-09-04 21:00", "2015-09-05 12:00", "2015 09-05 13:00", "2015 09-05 16:00", "2015 09-05 17:00"), time.OUT= c("2015-09-04 18:00", "NA", "NA","NA", "2015-09-05 13:21", "2015 09-05 16:48", "NA")) 

> tmpdf 
    spaceNum   time.IN   time.OUT 
1  1 2015-09-04 16:30 2015-09-04 18:00 
2  1 2015-09-04 19:50    NA 
3  1 2015-09-04 21:00    NA 
4  2 2015-09-05 12:00    NA 
5  2 2015 09-05 13:00 2015-09-05 13:21 
6  2 2015 09-05 16:00 2015 09-05 16:48 
7  2 2015 09-05 17:00    NA 
> 

我想的time.OUT NA值替换到的time.IN下一行值不是NULL并在相同的spaceNum组内。即,以下是我期待的结果。

spaceNum   time.IN   time.OUT 
    1  1 2015-09-04 16:30 2015-09-04 18:00 
    2  1 2015-09-04 19:50 2015-09-04 21:00 
    3  1 2015-09-04 21:00    NA 
    4  2 2015-09-05 12:00 2015-09-05 13:00 
    5  2 2015 09-05 13:00 2015-09-05 13:21 
    6  2 2015 09-05 16:00 2015 09-05 16:48 
    7  2 2015 09-05 17:00    NA 

这似乎dplyr或data.table可以做到这一点,我不得不寻找以前的问题,但是没有找到这个合适的路要走。

这可能是专家R用户的简单问题,但对我来说,它已经让我几个小时了,并没有找到好的解决方案。请帮帮我!!谢谢。

+0

您没有带提供了一个例子,当'time.IN'为NULL,它应该如何处理 –

+0

是你的真实也类的数据列'factor'在您的示例数据? –

+0

@David,为了简化问题,我想只是将time.OUT保留为NULL,如果time.IN的下一行值为NULL。 –

以下是可能的dplyr解决方案。这是ifelselead组合,而最终产品应该再次转换为as.POSIXct作为信息丢失的结果,由于使用的ifelse

library(dplyr) 
tmpdf %>% 
    group_by(spaceNum) %>% 
    mutate(time.OUT = as.POSIXct(ifelse(is.na(time.OUT), lead(time.IN), time.OUT), origin = "1970-01-01")) 
# Source: local data frame [7 x 3] 
# Groups: spaceNum 
# 
# spaceNum    time.IN   time.OUT 
# 1  1 2015-09-04 16:30:00 2015-09-04 18:00:00 
# 2  1 2015-09-04 19:50:00 2015-09-04 21:00:00 
# 3  1 2015-09-04 21:00:00    <NA> 
# 4  2 2015-09-05 12:00:00 2015-09-05 13:00:00 
# 5  2 2015-09-05 13:00:00 2015-09-05 13:21:00 
# 6  2 2015-09-05 16:00:00 2015-09-05 16:48:00 
# 7  2 2015-09-05 17:00:00    <NA> 
+1

谢谢大卫,它的作品! –

试试这个,

首先用字符向量构建df不是因素。 然后把所有的NA值放在sapplysapply中的函数找到当天发生的NA后的下一个time.IN。并从原来的df拉他们。最后将它们分配给df的NA值。

tmpdf <- data.frame(spaceNum=c(1,1,1,2,2,2,2), 
time.IN=c("2015-09-04 16:30", "2015-09-04 19:50", "2015-09-04 21:00", "2015-09-05 12:00", "2015 09-05 13:00", "2015 09-05 16:00", "2015 09-05 17:00"), 
time.OUT= c("2015-09-04 18:00", NA, NA,NA, "2015-09-05 13:21", "2015 09-05 16:48", NA),stringsAsFactors = F) 

tmp<-tmpdf[unlist(
      sapply(which(is.na(tmpdf[,3])),function(x){ 
       if(tmpdf[x,1]==tmpdf[x+1,1] && !is.na(tmpdf[x,1]==tmpdf[x+1,1])) x+1 
       else NA 
       })), 2] 

tmpdf[which(is.na(tmpdf[,3])),3]<-tmp 

> tmpdf 
    spaceNum   time.IN   time.OUT 
1  1 2015-09-04 16:30 2015-09-04 18:00 
2  1 2015-09-04 19:50 2015-09-04 21:00 
3  1 2015-09-04 21:00    <NA> 
4  2 2015-09-05 12:00 2015 09-05 13:00 
5  2 2015 09-05 13:00 2015-09-05 13:21 
6  2 2015 09-05 16:00 2015 09-05 16:48 
7  2 2015 09-05 17:00    <NA> 
+1

@Tensibai我正在写一些解释。谢谢btw。 – vck

+0

@vck,同样感谢你的支持sapply,BTW,它似乎有一个tydo,tmpdf [这是(is.na(tmpdf [,3])),3]

+0

@简志康是我更正了。 – vck

我们可以使用data.table做到这一点。在将'data.frame'转换为'data.table'(setDT(tmpdf))后,我们将factor'time'列转换为character类。在这里,我假设NA s是真实的NA而不是字符串。按'spaceNum'分组,我们使用data.table的devel版本中的shift创建一个新的列'v1'。在'time.out'中将'time.OUT'值分配给对应于NA元素的'v1'。我们也可以将不需要的列“NULL”,即“V1”

library(data.table)#v1.9.5+ 
setDT(tmpdf)[, (2:3) :=lapply(.SD, as.character), .SDcols=2:3] 
tmpdf[, v1:=shift(time.IN, type='lead'), spaceNum][is.na(time.OUT), 
        time.OUT:= v1][, v1:= NULL] 
tmpdf 
# spaceNum   time.IN   time.OUT 
#1:  1 2015-09-04 16:30 2015-09-04 18:00 
#2:  1 2015-09-04 19:50 2015-09-04 21:00 
#3:  1 2015-09-04 21:00    NA 
#4:  2 2015-09-05 12:00 2015 09-05 13:00 
#5:  2 2015 09-05 13:00 2015-09-05 13:21 
#6:  2 2015 09-05 16:00 2015 09-05 16:48 
#7:  2 2015 09-05 17:00    NA 

注意到,在本例中的数据集,除了性格"NA",我们也有多种格式的“时间”栏。即2015 09-05 16:482015-09-05 13:21。如果我们需要转换为POSIXct,我们可以使用library(lubridate),因为它可以采用多种格式。

library(lubridate) 
tmpdf[, (2:3) := lapply(.SD, ymd_hm), .SDcols=2:3] 
tmpdf 
# spaceNum    time.IN   time.OUT 
#1:  1 2015-09-04 16:30:00 2015-09-04 18:00:00 
#2:  1 2015-09-04 19:50:00 2015-09-04 21:00:00 
#3:  1 2015-09-04 21:00:00    <NA> 
#4:  2 2015-09-05 12:00:00 2015-09-05 13:00:00 
#5:  2 2015-09-05 13:00:00 2015-09-05 13:21:00 
#6:  2 2015-09-05 16:00:00 2015-09-05 16:48:00 
#7:  2 2015-09-05 17:00:00    <NA> 
+2

感谢akrun提供的data.table解决方案。 –

+0

@简志康Thanks for the upvote。 – akrun