我有这个数据框,dat和dplyr用于添加“NextStatTime”字段,该字段是ID结束时间之后的开始时间,“持续时间”是从结束时间到下次开始的时间时间为身份证。
数据如下所示:
dat = data.frame(ID= c(1,1,1,2,3,3),
NumberInSequence= c(1,3,4,1,1,2),
StartTime = as.POSIXct(c("2016-01-01 05:52:05 GMT","2016-01-01 05:52:11 GMT","2016-01-01 05:52:16 GMT","2016-01-01 05:40:05 GMT","2016-01-01 06:12:13 GMT","2016-01-01 07:12:26 GMT")) ,
EndTime = as.POSIXct(c("2016-01-01 05:52:10 GMT","2016-01-01 05:52:16 GMT","2016-01-01 05:52:30 GMT","2016-01-01 05:46:05 GMT","2016-01-01 06:12:25 GMT","2016-01-01 08:00:00 GMT") )
)
dat
dat %>% group_by(ID) %>% mutate(NextStartTime = lead(StartTime), duration = as.numeric(difftime(NextStartTime, EndTime, units = 's')))
ID NumberInSequence StartTime EndTime NextStartTime duration
<dbl> <dbl> <time> <time> <time> <dbl>
1 1 1 2016-01-01 05:52:05 2016-01-01 05:52:10 2016-01-01 05:52:11 1
2 1 3 2016-01-01 05:52:11 2016-01-01 05:52:16 2016-01-01 05:52:16 0
3 1 4 2016-01-01 05:52:16 2016-01-01 05:52:30 <NA> NA
4 2 1 2016-01-01 05:40:05 2016-01-01 05:46:05 <NA> NA
5 3 1 2016-01-01 06:12:13 2016-01-01 06:12:25 2016-01-01 07:12:26 3601
6 3 2 2016-01-01 07:12:26 2016-01-01 08:00:00 <NA> NA
这非常接近正确的答案,但如果缺少身份证,它仍会计算并产生误导。
例如 - 看ID = 1,有3个条目,序列号为1,3和4.序列中没有#2。它缺失所以NextStartTime和持续时间ID = 1和Number in sequence = 1应该是NA NOT 05:52:11和1.
有没有办法强加这种逻辑?
谢谢。
答案 0 :(得分:2)
我想使用POSIXct
留下替代方法。您可以通过以下方式避免数字到日期转换。如果在dplyr包中使用if_else()
,它会关心类。你想要做的是将POSIXct
类保留在函数中。如果您输入typeof(dat$StartTime)
,您会发现StartTime
是双倍的。它的类是POSIXct。因此,您希望使用NA_real_
并将NA视为POSIXct。请确保您提供原产地和时区。在我的情况下,我需要按顺序将我的时区指定为“亚洲/东京”或产生预期结果。
library(dplyr)
group_by(dat, ID) %>%
mutate(NextStartTime = if_else(abs(NumberInSequence - lead(NumberInSequence)) != 1,
true = as.POSIXct(NA_real_, origin = "1970-01-01 00:00:00", tz = "Asia/Tokyo"),
false = lead(StartTime)),
Duration = difftime(NextStartTime, EndTime, unit = "s"))
# ID NumberInSequence StartTime EndTime NextStartTime Duration
# <dbl> <dbl> <dttm> <dttm> <dttm> <time>
#1 1 1 2016-01-01 05:52:05 2016-01-01 05:52:10 <NA> NA secs
#2 1 3 2016-01-01 05:52:11 2016-01-01 05:52:16 2016-01-01 05:52:16 0 secs
#3 1 4 2016-01-01 05:52:16 2016-01-01 05:52:30 <NA> NA secs
#4 2 1 2016-01-01 05:40:05 2016-01-01 05:46:05 <NA> NA secs
#5 3 1 2016-01-01 06:12:13 2016-01-01 06:12:25 2016-01-01 07:12:26 3601 secs
#6 3 2 2016-01-01 07:12:26 2016-01-01 08:00:00 <NA> NA secs
答案 1 :(得分:1)
两个选项:
<script type="text/javascript">
function Link() {
document.getElementById("TestMe").src = "http://www.cnn.com";
}
</script>
<table>
<td bgcolor="#a7d331" height="10" align="center" style="cursor:pointer" onclick="window.open('http://www.yahoo.com'); Link();"><font face="Arial" color="FFFFFF" size="4" alt="English">Some Link</font></td>
</table>
<iframe id="TestMe" src="" frameborder="0" scrolling="no" width="400px" height="400px"></iframe>
一种选择是使用tidyr::complete
填写缺失的行,并使用上一种方法。
下行:您新添加了tidyr::complete
行。不过,你可以在事后小心NA
来省略它们
Upside :它易于编写和理解,并保留原始逻辑。
filter
带有library(tidyverse)
dat %>% group_by(ID) %>%
complete(NumberInSequence = seq(max(NumberInSequence))) %>%
mutate(NextStartTime = lead(StartTime),
Duration = as.numeric(difftime(NextStartTime, EndTime, units = 's')))
## Source: local data frame [7 x 6]
## Groups: ID [3]
##
## ID NumberInSequence StartTime EndTime NextStartTime Duration
## <dbl> <dbl> <dttm> <dttm> <dttm> <dbl>
## 1 1 1 2016-01-01 05:52:05 2016-01-01 05:52:10 <NA> NA
## 2 1 2 <NA> <NA> 2016-01-01 05:52:11 NA
## 3 1 3 2016-01-01 05:52:11 2016-01-01 05:52:16 2016-01-01 05:52:16 0
## 4 1 4 2016-01-01 05:52:16 2016-01-01 05:52:30 <NA> NA
## 5 2 1 2016-01-01 05:40:05 2016-01-01 05:46:05 <NA> NA
## 6 3 1 2016-01-01 06:12:13 2016-01-01 06:12:25 2016-01-01 07:12:26 3601
## 7 3 2 2016-01-01 07:12:26 2016-01-01 08:00:00 <NA> NA
的lead(StartTime)
ifelse
不方便剥离属性,因此如果不将结果整数重新转换回POSIXct,则无法执行ifelse
,这很麻烦。相反,使用ifelse(lead(StartTime) == NumberInSequence + 1, lead(StartTime), NA)
进行子集更容易,如果它不匹配则传递ifelse
,因此索引向量将返回NA
而不是任何内容。
下行:为了保持类型,写作很糟糕 上行:不会添加其他行。
NA