r - 在 R 中查找具有相同列类别的数据框中的上一个日期
问题描述
我有以下数据框:
Date.POSIXct Date WeekDay DayCategory Hour Holidays value
1 2018-05-01 00:00:00 2018-05-01 MA MA-MI-JU 0 0 30
2 2018-05-01 01:00:00 2018-05-01 MA MA-MI-JU 1 0 80
3 2018-05-01 02:00:00 2018-05-01 MA MA-MI-JU 2 0 42
4 2018-05-01 03:00:00 2018-05-01 MA MA-MI-JU 3 0 90
5 2018-05-01 04:00:00 2018-05-01 MA MA-MI-JU 4 0 95
6 2018-05-01 05:00:00 2018-05-01 MA MA-MI-JU 5 0 5
DayCategory 按以下方式对一周中的几天进行分组:Mondays 转到LU
DayCategory。周二、周三和周四转到MA-MI-JU
DayCategory。周五转至VI
,周六转至SA
,周日转至DO
类别。
我想在前一天 ( )中找到value
相同的相同,而仍然在同一组中(例如,如果一个实例有0,但前一天相同有 1,我们应该查找前一个,等等。 )hour
Date
DayCategory
Holidays
holiday
DayCategory
作为中间步骤并了解该过程,我想添加一个PreviousDaySameDayCategory
与Date
前一天具有相同DayCategory
对应行的列。有时它会date
减去 7 天(“LU”、“VI”、“SA”、“DO”),但其他日子只会是 1 天。
可重现的数据:
library(lubridate)
Date.POSIXct <- seq(as.POSIXct("2018-05-01"), as.POSIXct("2018-05-31"), "hour")
mydf <- as.data.frame(Date.POSIXct)
mydf$Date <- as.Date(substr(as.character(mydf$Date.POSIXct),1,10))
mydf$WeekDay <- substr(toupper((weekdays(mydf$Date))),1,2)
mydf$DayCategory <-as.factor(ifelse(mydf$WeekDay == "MA" | mydf$WeekDay == "MI" | mydf$WeekDay == "JU",
"MA-MI-JU", mydf$WeekDay))
mydf$Hour <- hour(mydf$Date.POSIXct)
mydf$Holidays <- c(rep(0, 24*7),rep(1, 24*7), rep(0, 24*16+1))
set.seed(123)
mydf$myvalue <- sample.int(101,size=nrow(mydf),replace=TRUE)
我已经手动开始了第一天,并创建了一个解决方案应该是什么样子的向量:
a <- rep(NA, 24)
b <- mydf$value[1:24]
c <- mydf$value[25:48]
d <- rep(NA, 24)
e <- rep(NA,24)
f <- rep(NA,24)
g <- rep(NA,24)
h <- rep(NA,24)
i <- mydf$value[169:192]
solution <- c(a,b,c,d,e,f,g,h,i)
solution
我将不胜感激思考过程中的任何提示,以解决我相对频繁面临的此类问题。
解决方案
这是一个data.table
解决方案,它使用“分组shift()
”和多个连接value
从相同hour
的PreviousDaySameDayCategory
.
创建可重现的数据
OP 创建可重现数据的代码不是完全可重现的,因为他使用了weekdays()
返回当前语言环境中的工作日名称的函数(对于 OP 来说似乎是西班牙语)。为了独立于当前的语言环境,我切换到format(Date, "%u")
返回数字 1 到 7 的星期一到星期日。此外,fct_collapse()
fromforcats
包用于将第 2 天、第 3 天和第 4 天(周二至周四)折叠为一个因子水平。
library(data.table)
# note that package lubridate is not required
myDT <- data.table(Date.POSIXct = seq(as.POSIXct("2018-05-01"),
as.POSIXct("2018-05-31"), "hour"))
myDT[, Date := as.Date(Date.POSIXct)]
myDT[, Weekday := format(Date, "%u")]
myDT[, DayCategory := forcats::fct_collapse(Weekday, "234" = c("2", "3", "4"))]
myDT[, hour := hour(Date.POSIXct)]
myDT[, Holidays := c(rep(0, 24 * 7), rep(1, 24 * 7), rep(0, 24 * 16 + 1))]
set.seed(123)
myDT[, myvalue := sample.int(101, size = nrow(mydf), replace = TRUE)]
中间步骤:PreviousDaySameDayCategory
样本数据集由每小时数据组成,但为了确定PreviousDaySameDayCategory
我们需要每天工作,因此只需处理 、 和 的Date
唯一DayCategory
值Holidays
。数据按DayCategory
和Holidays
指标分组。对于每个组,前一天由 lagging 选择Date
。由于shift()
操作的结果取决于数据集在移动之前已排序的行的顺序。
tmp <- unique(myDT[order(Date), .(Date, DayCategory, Holidays)])[
, .(Date, PreviousDaySameDayCategory = shift(Date)), by = .(DayCategory, Holidays)][
order(Date)]
tmp
DayCategory Holidays Date PreviousDaySameDayCategory 1: 234 0 2018-05-01 <NA> 2: 234 0 2018-05-02 2018-05-01 3: 234 0 2018-05-03 2018-05-02 4: 5 0 2018-05-04 <NA> 5: 6 0 2018-05-05 <NA> 6: 7 0 2018-05-06 <NA> 7: 1 0 2018-05-07 <NA> 8: 234 1 2018-05-08 <NA> 9: 234 1 2018-05-09 2018-05-08 10: 234 1 2018-05-10 2018-05-09 11: 5 1 2018-05-11 <NA> 12: 6 1 2018-05-12 <NA> 13: 7 1 2018-05-13 <NA> 14: 1 1 2018-05-14 <NA> 15: 234 0 2018-05-15 2018-05-03 16: 234 0 2018-05-16 2018-05-15 17: 234 0 2018-05-17 2018-05-16 18: 5 0 2018-05-18 2018-05-04 19: 6 0 2018-05-19 2018-05-05 20: 7 0 2018-05-20 2018-05-06 21: 1 0 2018-05-21 2018-05-07 22: 234 0 2018-05-22 2018-05-17 23: 234 0 2018-05-23 2018-05-22 24: 234 0 2018-05-24 2018-05-23 25: 5 0 2018-05-25 2018-05-18 26: 6 0 2018-05-26 2018-05-19 27: 7 0 2018-05-27 2018-05-20 28: 1 0 2018-05-28 2018-05-21 29: 234 0 2018-05-29 2018-05-24 30: 234 0 2018-05-30 2018-05-29 31: 234 0 2018-05-31 2018-05-30 DayCategory Holidays Date PreviousDaySameDayCategory
对于第 3 天和第 4 天(周三和周四),分别选择同一周的前一个周二和周三。对于第 2 天(星期二),如果两个星期都设置了相同的假期指示符,则选择前一周的前一个星期四。如果前一周有不同的假期指标,则选择同一假期的最近一个星期四。这就是为什么,例如,2018-05-03 在第 15 行中被选中。
value
从匹配复制PreviousDaySameDayCategory
这分两步完成。PreviousDaySameDayCategory
首先,通过加入匹配天数表从匹配中挑选小时值tmp
:
tmp2 <- myDT[tmp, on = .(Date = PreviousDaySameDayCategory), .(Date = i.Date, hour, myvalue), nomatch = 0L]
tmp2
Date hour myvalue 1: 2018-05-02 0 30 2: 2018-05-02 1 80 3: 2018-05-02 2 42 4: 2018-05-02 3 90 5: 2018-05-02 4 95 --- 500: 2018-05-31 19 39 501: 2018-05-31 20 1 502: 2018-05-31 21 1 503: 2018-05-31 22 101 504: 2018-05-31 23 11
其次,通过更新包含来自 的相应值的连接previousValue
来myDT
创建一个新列:PreviousDaySameDayCategory
myDT[tmp2, on = .(Date, hour), previousValue := i.myvalue]
这里显示了前两天的结果:
myDT[Date %between% c(as.Date("2018-05-01"), as.Date("2018-05-02"))]
Date.POSIXct Date Weekday DayCategory hour Holidays myvalue previousValue 1: 2018-05-01 00:00:00 2018-05-01 2 234 0 0 30 NA 2: 2018-05-01 01:00:00 2018-05-01 2 234 1 0 80 NA 3: 2018-05-01 02:00:00 2018-05-01 2 234 2 0 42 NA 4: 2018-05-01 03:00:00 2018-05-01 2 234 3 0 90 NA 5: 2018-05-01 04:00:00 2018-05-01 2 234 4 0 95 NA 6: 2018-05-01 05:00:00 2018-05-01 2 234 5 0 5 NA 7: 2018-05-01 06:00:00 2018-05-01 2 234 6 0 54 NA 8: 2018-05-01 07:00:00 2018-05-01 2 234 7 0 91 NA 9: 2018-05-01 08:00:00 2018-05-01 2 234 8 0 56 NA 10: 2018-05-01 09:00:00 2018-05-01 2 234 9 0 47 NA 11: 2018-05-01 10:00:00 2018-05-01 2 234 10 0 97 NA 12: 2018-05-01 11:00:00 2018-05-01 2 234 11 0 46 NA 13: 2018-05-01 12:00:00 2018-05-01 2 234 12 0 69 NA 14: 2018-05-01 13:00:00 2018-05-01 2 234 13 0 58 NA 15: 2018-05-01 14:00:00 2018-05-01 2 234 14 0 11 NA 16: 2018-05-01 15:00:00 2018-05-01 2 234 15 0 91 NA 17: 2018-05-01 16:00:00 2018-05-01 2 234 16 0 25 NA 18: 2018-05-01 17:00:00 2018-05-01 2 234 17 0 5 NA 19: 2018-05-01 18:00:00 2018-05-01 2 234 18 0 34 NA 20: 2018-05-01 19:00:00 2018-05-01 2 234 19 0 97 NA 21: 2018-05-01 20:00:00 2018-05-01 2 234 20 0 90 NA 22: 2018-05-01 21:00:00 2018-05-01 2 234 21 0 70 NA 23: 2018-05-01 22:00:00 2018-05-01 2 234 22 0 65 NA 24: 2018-05-01 23:00:00 2018-05-01 2 234 23 0 101 NA 25: 2018-05-02 00:00:00 2018-05-02 3 234 0 0 67 30 26: 2018-05-02 01:00:00 2018-05-02 3 234 1 0 72 80 27: 2018-05-02 02:00:00 2018-05-02 3 234 2 0 55 42 28: 2018-05-02 03:00:00 2018-05-02 3 234 3 0 61 90 29: 2018-05-02 04:00:00 2018-05-02 3 234 4 0 30 95 30: 2018-05-02 05:00:00 2018-05-02 3 234 5 0 15 5 31: 2018-05-02 06:00:00 2018-05-02 3 234 6 0 98 54 32: 2018-05-02 07:00:00 2018-05-02 3 234 7 0 92 91 33: 2018-05-02 08:00:00 2018-05-02 3 234 8 0 70 56 34: 2018-05-02 09:00:00 2018-05-02 3 234 9 0 81 47 35: 2018-05-02 10:00:00 2018-05-02 3 234 10 0 3 97 36: 2018-05-02 11:00:00 2018-05-02 3 234 11 0 49 46 37: 2018-05-02 12:00:00 2018-05-02 3 234 12 0 77 69 38: 2018-05-02 13:00:00 2018-05-02 3 234 13 0 22 58 39: 2018-05-02 14:00:00 2018-05-02 3 234 14 0 33 11 40: 2018-05-02 15:00:00 2018-05-02 3 234 15 0 24 91 41: 2018-05-02 16:00:00 2018-05-02 3 234 16 0 15 25 42: 2018-05-02 17:00:00 2018-05-02 3 234 17 0 42 5 43: 2018-05-02 18:00:00 2018-05-02 3 234 18 0 42 34 44: 2018-05-02 19:00:00 2018-05-02 3 234 19 0 38 97 45: 2018-05-02 20:00:00 2018-05-02 3 234 20 0 16 90 46: 2018-05-02 21:00:00 2018-05-02 3 234 21 0 15 70 47: 2018-05-02 22:00:00 2018-05-02 3 234 22 0 24 65 48: 2018-05-02 23:00:00 2018-05-02 3 234 23 0 48 101 Date.POSIXct Date Weekday DayCategory hour Holidays myvalue previousValue
确认
结果符合OP的预期
identical(myDT[, previousValue[seq_along(solution)]], solution)
[1] TRUE
推荐阅读
- python - 将列表与元组列表进行比较?
- composer-php - 使用 Composer 安装 mailparser,为什么我得到一个错误,即 allow_url_fopen 已经启用时必须启用它?
- python - 谷歌 BigQuery WRITE_TRUNCATE 删除所有数据
- c - SDL_BlitSurface 总是模糊的。我究竟做错了什么?
- ruby - Phusion 乘客正在覆盖我的数据库配置
- algorithm - 每日编码问题,1.4:解决方案中给出的运行时间不正确?
- react-native - 如何在 componentDidMount 中使用 if/else 和 responseJson?
- scikit-learn - 为什么 scikit 中的 KNN 算法没有按预期工作?
- shell - 有没有一种快速的方法来读取 dd 中的备用字节
- angular - 在组件之间共享数据(Angular 5,复杂应用)