在R中使用相同列类别查找数据框中的上一个日期

时间:2018-05-28 16:03:47

标签: r dataframe dplyr data.table

我有以下数据框:

      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按以下方式分组星期几:星期一转到LU DayCategory。星期二,星期三和星期四转到MA-MI-JU DayCategory。 星期五分别到VI,星期六到SA,星期日到DO分类。

我希望在前一天(value)找到同一hour Date DayCategory Holidays,而holiday仍在DayCategory内相同的组(例如,如果一个实例有PreviousDaySameDayCategory 0但前一天有相同的Date有1,我们应该看看前一个等等。)

作为中间步骤并且为了理解该过程,我想添加一个列DayCategory,其中前一天的date与相应的行具有相同的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 减去七天(&#34; LU&#34;,&#34; VI&#34;,&#34; SA&#34;,&#34; DO&# 34;)但其他日子只有一天。

可重复数据:

{{1}}

我已经手动启动了第一天,并提出了解决方案应该如何的向量:

{{1}}

我很感激思维过程中的任何暗示,以相对频率解决我面临的这类问题。

2 个答案:

答案 0 :(得分:1)

以下是data.table解决方案,该解决方案使用“分组shift()”和多个联接来复制value hour的{​​{1}}。< / p>

创建可重现的数据

用于创建可重现数据的OP代码不能完全重现,因为他使用PreviousDaySameDayCategory函数返回当前语言环境中的工作日名称(OP似乎是西班牙语)。为了独立于当前的语言环境,我切换到weekdays(),它返回星期一到星期日的数字1到7。此外,format(Date, "%u")包中的fct_collapse()用于将第2,3和4天(周二到周四)折叠为一个因子级别。

forcats

中级步骤: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,{{1}的唯一值}和Date。数据按DayCategoryHolidays指标进行分组。对于每个组,前一天选择滞后DayCategory。由于Holidays操作的结果取决于数据集在移位之前的排序行。

Date
shift()

在第3天和第4天(周三和周四),选择同一周的周二和周三。对于第2天(星期二),如果两周都有相同的假期指标设置,那么前一周的前一周将被选中。如果前一周有不同的假期指标,则选择同一假期的最近一个星期四。这就是为什么,例如2018-05-03在第15行被选中。

从匹配的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

这分两步完成。首先,通过加入匹配的日期表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]

验证

结果符合OP的预期

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

答案 1 :(得分:1)

OP也在数据科学部分发布了相同的问题。我在这里包含了相同的解决方案,这可能对其他人有帮助。 它类似于Uwe的解决方案,但改为使用dplyr库。

library(dplyr)
rankedDf <- mydf %>%
  group_by(DayCategory, Hour, Holidays) %>%
  arrange(Date) %>%
  mutate(rowRank = order(Date), previousRowRank = order(Date) - 1) %>%
  left_join(., ., by = c("previousRowRank" = "rowRank", "DayCategory", "Hour", "Holidays")) %>%
  select(
  Date.POSIXct = Date.POSIXct.x,
  Date = Date.x,
  WeekDay = WeekDay.x,
  DayCategory,
  Hour,
  Holidays,
  myvalue = myvalue.x,
  PreviousDaySameDayCategory = Date.y,
  PreviousValueSameDayCategory = myvalue.y
)
print.data.frame(rankedDf)

P.S。喜欢Uwe改变原始示例代码的方式。