Commit | Line | Data |
---|---|---|
3a38473a BA |
1 | #' dateIndexToInteger |
2 | #' | |
3 | #' Transform a (potential) date index into an integer (relative to data beginning). | |
4 | #' | |
5 | #' @param index Date (or integer) index | |
6 | #' @param data Object of class Data, output of \code{getData()} | |
7 | #' | |
8 | #' @export | |
9 | dateIndexToInteger = function(index, data) | |
10 | { | |
11 | # Works on integers too: trust input | |
12 | if (is.numeric(index)) | |
13 | index = as.integer(index) | |
14 | if (is.integer(index)) | |
15 | return (index) | |
16 | ||
17 | if (inherits(index, "Date") || is.character(index)) | |
18 | { | |
19 | tryCatch(indexAsDate <- as.Date(index), | |
20 | error=function(e) stop("Unrecognized index format")) | |
21 | #TODO: tz arg to difftime ? | |
22 | integerIndex <- round( as.numeric( | |
23 | difftime(indexAsDate, as.Date(data$getTime(1)[1])) ) ) + 1 | |
24 | if (integerIndex >= 1 && integerIndex <= data$getSize()) | |
25 | return (integerIndex) | |
26 | stop("Date outside data range") | |
27 | } | |
28 | stop("Unrecognized index format") | |
29 | } | |
30 | ||
31 | #' integerIndexToDate | |
32 | #' | |
33 | #' Transform an integer index (relative to data beginning) into a date index. | |
34 | #' | |
35 | #' @inheritParams dateIndexToInteger | |
36 | #' | |
37 | #' @export | |
38 | integerIndexToDate = function(index, data) | |
39 | { | |
40 | # Works on dates too: trust input | |
41 | if (is.character(index)) | |
42 | index = as.Date(index) | |
43 | if (is(index,"Date")) | |
44 | return (index) | |
45 | ||
46 | index = index[1] | |
47 | if (is.numeric(index)) | |
48 | index = as.integer(index) | |
49 | if (!is.integer(index)) | |
50 | stop("'index' should be a date or integer") | |
51 | as.Date( data$getTime(index)[1] ) | |
52 | } | |
53 | ||
54 | #' getSimilarDaysIndices | |
55 | #' | |
56 | #' Find similar days indices in the past; at least same type of day in the week: | |
57 | #' monday=tuesday=wednesday=thursday != friday != saturday != sunday. | |
58 | #' | |
59 | #' @param index Day index (numeric or date) | |
60 | #' @param data Reference dataset, object output of \code{getData} | |
61 | #' @param limit Maximum number of indices to return | |
62 | #' @param same_season Should the indices correspond to day in same season? | |
63 | #' @param days_in Optional set to intersect with results (NULL to discard) | |
64 | #' @param operational If TRUE: do not look for days after index (operational context) | |
65 | #' | |
66 | #' @export | |
67 | getSimilarDaysIndices = function(index, data, limit, same_season, | |
68 | days_in=NULL, operational=TRUE) | |
69 | { | |
70 | index = dateIndexToInteger(index, data) | |
71 | ||
72 | # Look for similar days (optionally in same season) | |
73 | days = c() | |
74 | dt_ref = as.POSIXlt(data$getTime(index)[1]) #first date-time of current day | |
75 | day_ref = dt_ref$wday #1=monday, ..., 6=saturday, 0=sunday | |
76 | month_ref = as.POSIXlt(data$getTime(index)[1])$mon+1 #month in 1...12 | |
77 | i = index - 1 | |
78 | if (!operational) | |
79 | j = index + 1 | |
80 | while (length(days) < min( limit, ifelse(is.null(days_in),Inf,length(days_in)) )) | |
81 | { | |
82 | if (i < 1 && j > data$getSize()) | |
83 | break | |
84 | if (i >= 1) | |
85 | { | |
86 | dt = as.POSIXlt(data$getTime(i)[1]) | |
87 | if ((is.null(days_in) || i %in% days_in) && .isSameDay(dt$wday, day_ref)) | |
88 | { | |
89 | if (!same_season || .isSameSeason(dt$mon+1, month_ref)) | |
90 | days = c(days, i) | |
91 | } | |
92 | i = i - 1 | |
93 | } | |
94 | if (!operational && j <= data$getSize()) | |
95 | { | |
96 | dt = as.POSIXlt(data$getTime(j)[1]) | |
97 | if ((is.null(days_in) || j %in% days_in) && .isSameDay(dt$wday, day_ref)) | |
98 | { | |
99 | if (!same_season || .isSameSeason(dt$mon+1, month_ref)) | |
100 | days = c(days, j) | |
101 | } | |
102 | j = j + 1 | |
103 | } | |
104 | } | |
105 | return ( days ) | |
106 | } | |
107 | ||
108 | # isSameSeason | |
109 | # | |
110 | # Check if two months fall in the same "season" (defined by estimated pollution rate). | |
111 | # | |
112 | # @param month Month index to test | |
113 | # @param month_ref Month to compare to | |
114 | # | |
115 | .isSameSeason = function(month, month_ref) | |
116 | { | |
117 | # if (month_ref == 3) #TODO: same as Bruno (but weird) | |
118 | # return (month %in% c(2,3,4,9,10)) | |
119 | if (month_ref %in% c(11,12,1,2)) #~= mid-polluted | |
120 | return (month %in% c(11,12,1,2)) | |
121 | if (month_ref %in% c(3,4,9,10)) #~= high-polluted | |
122 | return (month %in% c(3,4,9,10)) | |
123 | return (month %in% c(5,6,7,8)) #~= non polluted | |
124 | } | |
125 | ||
126 | # isSameDay | |
127 | # | |
128 | # Monday=Tuesday=Wednesday=Thursday ; Friday, Saturday, Sunday: specials. | |
129 | # | |
130 | # @param day Day index to test | |
131 | # @param day_ref Day index to compare to | |
132 | # | |
133 | .isSameDay = function(day, day_ref) | |
134 | { | |
135 | if (day_ref %in% 1:4) | |
136 | return (day %in% 1:4) | |
137 | return (day == day_ref) | |
138 | } | |
139 | ||
140 | # getNoNA2 | |
141 | # | |
142 | # Get indices in data of no-NA series preceded by no-NA, within [first,last] range. | |
143 | # | |
144 | # @inheritParams dateIndexToInteger | |
145 | # @param first First index (included) | |
146 | # @param last Last index (included) | |
147 | # | |
148 | .getNoNA2 = function(data, first, last) | |
149 | { | |
150 | (first:last)[ sapply(first:last, function(i) | |
151 | !any( is.na(data$getSerie(i-1)) | is.na(data$getSerie(i)) ) | |
152 | ) ] | |
153 | } |