如何在连续日期的每个夜间创建唯一ID?

时间:2016-12-12 23:58:33

标签: r time time-series uniqueidentifier

我连续几天连续收集数据。每个观察已经包含变量datetime(POSIXct对象)和par(数字对象)。我想创建一个名为ID的新变量,它将是一个与单个夜间相关联的唯一数字。我将夜间时间定义为par = 0的所有观测值。我希望我的数据看起来像一个例子,连续3天在下面给出。

注意:我的实际数据是每隔15分钟拍摄一次,但我截断了此示例以便于查看。

              datetime    par    ID
1  2015-04-23 00:00:00    0.0     1
2  2015-04-23 08:00:00    0.0     1
3  2015-04-23 12:00:00  817.7     0
4  2015-04-23 19:00:00    0.0     2
5  2015-04-24 00:00:00    0.0     2
6  2015-04-24 08:00:00    0.0     2
7  2015-04-24 12:00:00  269.9     0
8  2015-04-24 19:00:00    0.0     3
9  2015-04-25 00:00:00    0.0     3
10 2015-04-25 08:00:00    0.0     3
11 2015-04-25 12:00:00 1701.8     0
12 2015-04-25 19:00:00    0.0     4
13 2015-04-25 23:00:00    0.0     4

我希望非夜晚(par!= 0)观察ID = 0.第一个夜间时间发生在2015年4月23日,所以我想要它的ID = 1.然后我想添加1到每个夜晚时段ID。

有什么想法吗?尽管付出了很多努力,但我还是无法取得上述成果。提前谢谢。

3 个答案:

答案 0 :(得分:4)

使用cumsum

df$ID2 <- 0
sel <- df$par == 0
df$ID2[sel] <- cumsum(!sel)[sel] + 1

#      par ID ID2
#1     0.0  1   1
#2     0.0  1   1
#3   817.7  0   0
#4     0.0  2   2
#5     0.0  2   2
#6     0.0  2   2
#7   269.9  0   0
#8     0.0  3   3
#9     0.0  3   3
#10    0.0  3   3
#11 1701.8  0   0
#12    0.0  4   4
#13    0.0  4   4

答案 1 :(得分:2)

我首先将您的POSIXct日期转换为POSIXlt日期,因为这些日期可以让您更轻松地确定日期。

df[["datetime"]] <- as.POSIXlt(df[["datetime"]])

然后,我们可以使用字段ydayhour来获取数值,其中24小时内a中午的任何内容具有相同的值。这只适用于所有时间都在同一年的情况。如果没有,则必须使用year属性来调整日期。

indicator <- df[["datetime"]][["yday"]] + (df[["datetime"]][["hour"]] > 12)

使用因子水平,我们可以从1开始获得订单号。

df[["ID"]] <- as.numeric(as.factor(indicator))

然后我们可以将所有day句点设置为0

df[["ID"]][df[["par"]] != 0] <- 0

如果需要,可以用两行完成。

df[["ID"]] <- as.numeric(as.factor(df[["datetime"]][["yday"]] + 
                                (df[["datetime"]][["hour"]] > 12)))
df[["ID"]][df[["par"]] != 0] <- 0

无论数据的顺序如何,此解决方案都能正常运行。

答案 2 :(得分:1)

有两种方法,都采用游程编码

data.table

这使用了时间段按日期分组的事实,因此我们可以使用run-length-encoding对同一日期的值进行分组。然后,par > 0的任何内容都可以设置为0.

library(data.table)

setDT(df)
## explicitly ordering the data.table
df[order(datetime), ID := rleid(as.Date(datetime))][ par > 0, ID := 0]
df
#               datetime    par ID
# 1:  2015-04-23 00:00:00    0.0  1
# 2:  2015-04-23 08:00:00    0.0  1
# 3:  2015-04-23 12:00:00  817.7  0
# 4:  2015-04-23 19:00:00    0.0  2
# 5:  2015-04-24 00:00:00    0.0  2
# 6:  2015-04-24 08:00:00    0.0  2
# 7:  2015-04-24 12:00:00  269.9  0
# 8:  2015-04-24 19:00:00    0.0  3
# 9:  2015-04-25 00:00:00    0.0  3
# 10: 2015-04-25 08:00:00    0.0  3
# 11: 2015-04-25 12:00:00 1701.8  0
# 12: 2015-04-25 19:00:00    0.0  4
# 13: 2015-04-25 23:00:00    0.0  4

(这是我首选的解决方案,因为它可以处理任何日期,正确排序数据,并且效率很高,因为,你知道,data.table ......)

如果'夜晚时段'总是以“白天”时段分隔,那么您也可以这样做

## create an ID column set the 'daytime' periods to 0
df[ df$par != 0, "ID"] <- 0

## get the run-length-encoding of the ID column
r <- rle(is.na(df$ID))

## the length of the rle where the value is TRUE gives us teh number of NAs in each 'group', so we can replicate the rle value by that amount
rep(1:length(r$lengths[r$values]), r$length[r$values])
# [1] 1 1 2 2 2 3 3 3 4 4

## so you can fill the rest of hte column with these values

df[ df$par == 0, "ID"] <- rep(1:length(r$lengths[r$values]), r$length[r$values])
df
#               datetime    par ID
# 1  2015-04-23 00:00:00    0.0  1
# 2  2015-04-23 08:00:00    0.0  1
# 3  2015-04-23 12:00:00  817.7  0
# 4  2015-04-23 19:00:00    0.0  2
# 5  2015-04-24 00:00:00    0.0  2
# 6  2015-04-24 08:00:00    0.0  2
# 7  2015-04-24 12:00:00  269.9  0
# 8  2015-04-24 19:00:00    0.0  3
# 9  2015-04-25 00:00:00    0.0  3
# 10 2015-04-25 08:00:00    0.0  3
# 11 2015-04-25 12:00:00 1701.8  0
# 12 2015-04-25 19:00:00    0.0  4
# 13 2015-04-25 23:00:00    0.0  4