dplyr mutate函数,用于垂直计算列(当前、上一个、下一个)中的值

dplyr mutate函数,用于垂直计算列(当前、上一个、下一个)中的值,r,dplyr,R,Dplyr,我一直在寻找一种不用运气就能实现我所需要的东西的方法。 不久前,我发现了dplyr包及其潜力。我在想这个包裹可以做我想做的,我只是不知道怎么做。这是我数据的一小部分,但应该代表我的问题 dummy<-structure(list(time = structure(1:20, .Label = c("2015-03-25 12:24:00", "2015-03-25 21:08:00", "2015-03-25 21:13:00", "2015-03-25 21:47:00

我一直在寻找一种不用运气就能实现我所需要的东西的方法。 不久前,我发现了dplyr包及其潜力。我在想这个包裹可以做我想做的,我只是不知道怎么做。这是我数据的一小部分,但应该代表我的问题

    dummy<-structure(list(time = structure(1:20, .Label = c("2015-03-25 12:24:00", 
    "2015-03-25 21:08:00", "2015-03-25 21:13:00", "2015-03-25 21:47:00", 
    "2015-03-26 03:08:00", "2015-04-01 20:30:00", "2015-04-01 20:34:00", 
    "2015-04-01 20:42:00", "2015-04-01 20:45:00", "2015-09-29 18:26:00", 
    "2015-09-29 19:11:00", "2015-09-29 21:21:00", "2015-09-29 22:03:00", 
    "2015-09-29 22:38:00", "2015-09-30 00:48:00", "2015-09-30 01:38:00", 
    "2015-09-30 01:41:00", "2015-09-30 01:45:00", "2015-09-30 01:47:00", 
    "2015-09-30 01:49:00"), class = "factor"), ID = c(1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L), station = c(1L, 1L, 1L, 2L, 3, 
    4L, 4L, 4L, 4L, 5L, 5L, 6L, 
    6L, 5, 5, 5L, 7, 7, 7L, 
    7)), .Names = c("time", "ID", "station"), class = "data.frame", row.names = c(NA, 
    -20L))

这里有一个使用
difftime
dplyr
mutate函数的选项。首先,我们使用
groupu by
操作来确保比较在ID和Station的每个唯一组合内。
difftime
可用于计算差分时间,为方便起见,此处将单位设置为
hours
lag
lead
功能也来自
dplyr
软件包,用于向后或向前移动所选列。结合difftime的矢量化操作,可以计算当前行与上一行/下一行之间的时间差。我们使用
abs
来确保结果是绝对值。
%group\u by(ID,station)%%>%
变异(new.value=as.integer(
abs(difftime(time,lag(time,default=Inf),units=“hours”)<1 |
abs(difftime(时间,提前期(时间,默认值=Inf),units=“hours”)<1))
来源:本地数据帧[20 x 4]
分组:ID,站点[7]
时间ID station new.value
(时间)(int)(dbl)(int)
1  2015-03-25 12:24:00     1       1         0
2  2015-03-25 21:08:00     1       1         1
3  2015-03-25 21:13:00     1       1         1
4  2015-03-25 21:47:00     1       2         0
5  2015-03-26 03:08:00     1       3         0
6  2015-04-01 20:30:00     1       4         1
7  2015-04-01 20:34:00     1       4         1
8  2015-04-01 20:42:00     1       4         1
9  2015-04-01 20:45:00     1       4         1
10 2015-09-29 18:26:00     2       5         1
11 2015-09-29 19:11:00     2       5         1
12 2015-09-29 21:21:00     2       6         1
13 2015-09-29 22:03:00     2       6         1
14 2015-09-29 22:38:00     2       5         0
15 2015-09-30 00:48:00     2       5         1
16 2015-09-30 01:38:00     2       5         1
17 2015-09-30 01:41:00     2       7         1
18 2015-09-30 01:45:00     2       7         1
19 2015-09-30 01:47:00     2       7         1
20 2015-09-30 01:49:00     2       7         1
Psidom的答案很好——这里有一个
数据表方法

library(data.table)
setDT(dummy)
# you do NOT want a factor for your time variable
dummy[, time := as.POSIXct(time) ]
dummy[, `:=`(lag_diff = c(Inf, diff(as.numeric(time))),
             lead_diff = c(diff(as.numeric(time)), Inf)),
      by = .(ID, station) ]
dummy[, new.value := as.integer(lag_diff < 3600 | lead_diff < 3600) ]
dummy
库(data.table)
setDT(虚拟)
#您不希望为时间变量指定一个因子
虚拟对象[,时间:=as.POSIXct(时间)]
dummy[,`:=`(lag_diff=c(Inf,diff(as.numeric(time))),
导程_diff=c(diff(作为数值(时间)),Inf)),
by=(ID,车站)]
dummy[,new.value:=as.integer(滞后_diff<3600 |超前_diff<3600)]
笨蛋

另一种使用R基函数的解决方案(
sapply
difftime
):

n=nrow(虚拟)
虚拟$new.value=
as.numeric(sapply(1:n,函数(i))

(我认为您不需要dplyr,我认为您只需要几个
diff
操作。请注意,“Class”POSIXct“表示自1970年初以来(UTC时区)的(有符号)秒数,作为一个数字向量。”因此,您希望查找小于3600秒的差异。不确定是否有
dplyr
,但data.table具有滚动联接,似乎可以以最有效的方式解决您的问题。最近的一篇文章详细介绍了该功能:。要提供一小时滚动,只需使用60*60(因为POSIXct是秒数)。通过这种方式,您应该能够使用二进制合并来检测这些行。如果纯性能不是您的目标,那么
shift(x)
c(NA,x[-.N])
/
c(x[-1L],NA)
应该足以创建要比较的列。这确实是我想要的。请您详细说明一下,谢谢。
library(dplyr)
dummy %>% group_by(ID, station) %>% 
          mutate(new.value = as.integer(
                 abs(difftime(time, lag(time, default = Inf), units = "hours")) < 1 | 
                 abs(difftime(time, lead(time, default = Inf), units = "hours")) < 1))

Source: local data frame [20 x 4]
Groups: ID, station [7]

                  time    ID station new.value
                (time) (int)   (dbl)     (int)
1  2015-03-25 12:24:00     1       1         0
2  2015-03-25 21:08:00     1       1         1
3  2015-03-25 21:13:00     1       1         1
4  2015-03-25 21:47:00     1       2         0
5  2015-03-26 03:08:00     1       3         0
6  2015-04-01 20:30:00     1       4         1
7  2015-04-01 20:34:00     1       4         1
8  2015-04-01 20:42:00     1       4         1
9  2015-04-01 20:45:00     1       4         1
10 2015-09-29 18:26:00     2       5         1
11 2015-09-29 19:11:00     2       5         1
12 2015-09-29 21:21:00     2       6         1
13 2015-09-29 22:03:00     2       6         1
14 2015-09-29 22:38:00     2       5         0
15 2015-09-30 00:48:00     2       5         1
16 2015-09-30 01:38:00     2       5         1
17 2015-09-30 01:41:00     2       7         1
18 2015-09-30 01:45:00     2       7         1
19 2015-09-30 01:47:00     2       7         1
20 2015-09-30 01:49:00     2       7         1
library(data.table)
setDT(dummy)
# you do NOT want a factor for your time variable
dummy[, time := as.POSIXct(time) ]
dummy[, `:=`(lag_diff = c(Inf, diff(as.numeric(time))),
             lead_diff = c(diff(as.numeric(time)), Inf)),
      by = .(ID, station) ]
dummy[, new.value := as.integer(lag_diff < 3600 | lead_diff < 3600) ]
dummy
n=nrow(dummy)
dummy$new.value=
as.numeric(sapply(1:n, function(i) 
(i<n && (dummy[i,"ID"]==dummy[i+1,"ID"] && dummy[i,"station"]==dummy[i+1,"station"]) 
&& abs(as.numeric(difftime(dummy[i,"time"], dummy[i+1,"time"]), "hours"))<=1) 
|| 
(i>1 && (dummy[i,"ID"]==dummy[i-1,"ID"] && dummy[i,"station"]==dummy[i-1,"station"]) 
&& abs(as.numeric(difftime(dummy[i,"time"], dummy[i-1,"time"]), "hours"))<=1) 
))

# > dummy
                  # time ID station new.value
# 1  2015-03-25 12:24:00  1       1         0
# 2  2015-03-25 21:08:00  1       1         1
# 3  2015-03-25 21:13:00  1       1         1
# 4  2015-03-25 21:47:00  1       2         0
# 5  2015-03-26 03:08:00  1       3         0
# 6  2015-04-01 20:30:00  1       4         1
# 7  2015-04-01 20:34:00  1       4         1
# 8  2015-04-01 20:42:00  1       4         1
# 9  2015-04-01 20:45:00  1       4         1
# 10 2015-09-29 18:26:00  2       5         1
# 11 2015-09-29 19:11:00  2       5         1
# 12 2015-09-29 21:21:00  2       6         1
# 13 2015-09-29 22:03:00  2       6         1
# 14 2015-09-29 22:38:00  2       5         0
# 15 2015-09-30 00:48:00  2       5         1
# 16 2015-09-30 01:38:00  2       5         1
# 17 2015-09-30 01:41:00  2       7         1
# 18 2015-09-30 01:45:00  2       7         1
# 19 2015-09-30 01:47:00  2       7         1
# 20 2015-09-30 01:49:00  2       7         1