我连续几天连续收集数据。每个观察已经包含变量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。
有什么想法吗?尽管付出了很多努力,但我还是无法取得上述成果。提前谢谢。
答案 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"]])
然后,我们可以使用字段yday
和hour
来获取数值,其中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)
有两种方法,都采用游程编码
这使用了时间段按日期分组的事实,因此我们可以使用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