Skip to content

Commit 21f36a2

Browse files
author
Jordan S Read
committed
Merge pull request #42 from jread-usgs/master
rolling window for MAD(x,w)
2 parents cf85043 + 5f8d1c2 commit 21f36a2

File tree

13 files changed

+110
-16
lines changed

13 files changed

+110
-16
lines changed

DESCRIPTION

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: sensorQC
22
Type: Package
33
Title: sensorQC
4-
Version: 0.3.4
4+
Version: 0.4.0
55
Date: 2015-10-23
66
Author: Jordan S Read, Brad Garner, Brian Pellerin, Luke Loken
77
Maintainer: Jordan S Read <[email protected]>
@@ -15,9 +15,11 @@ Copyright: This software is in the public domain because it contains materials
1515
Imports:
1616
yaml,
1717
dplyr,
18+
RcppRoll,
1819
lazyeval,
1920
readr
2021
Suggests:
2122
testthat
2223
LazyLoad: yes
2324
LazyData: yes
25+
RoxygenNote: 5.0.0

NAMESPACE

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by roxygen2 (4.1.1): do not edit by hand
1+
# Generated by roxygen2: do not edit by hand
22

33
S3method("[",sensor)
44
S3method(calc_flags,sensor)
@@ -24,6 +24,7 @@ export(persist)
2424
export(read)
2525
export(read.default)
2626
export(sensor)
27+
importFrom(RcppRoll,roll_median)
2728
importFrom(dplyr,"%>%")
2829
importFrom(dplyr,group_by_)
2930
importFrom(dplyr,mutate_)

R/custom-functions.R

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,44 @@ MAD.values <- function(vals, b = 1.4826){
1414
return(MAD.normalized)
1515
}
1616

17+
18+
MAD.roller <- function(vals, window){
19+
b = 1.4826
20+
warning('MAD.roller function has not been robustly tested w/ NAs')
21+
u.i <- is.finite(vals)
22+
left.fill <- median(head(vals[u.i], ceiling(window/2)))
23+
right.fill <- median(tail(vals[u.i], ceiling(window/2)))
24+
medians <- roll_median(vals[u.i], n=window, fill=c(left.fill, 0, right.fill))
25+
abs.med.diff <- abs(vals[u.i]-medians)
26+
left.fill <- median(head(abs.med.diff, ceiling(window/2)))
27+
right.fill <- median(tail(abs.med.diff, ceiling(window/2)))
28+
abs.med <- roll_median(abs.med.diff, n=window, fill=c(left.fill, 0, right.fill))
29+
MAD <- abs.med*b
30+
MAD.normalized = rep(NA,length(vals))
31+
MAD.normalized[u.i] <- abs.med.diff/MAD # division by zero
32+
MAD.normalized[is.na(MAD.normalized)] <- 0
33+
return(MAD.normalized)
34+
}
35+
1736
MAD.windowed <- function(vals, windows){
37+
1838
stopifnot(length(vals) == length(windows))
19-
. <- '_dplyr_var'
20-
mad <- group_by_(data.frame(x=vals,w=windows), 'w') %>% mutate_(mad='sensorQC:::MAD.values(x)') %>% .$mad
21-
return(mad)
39+
if (length(unique(windows)) == 1){
40+
w = unique(windows)
41+
x = vals
42+
return(MAD.roller(x, w))
43+
} else {
44+
. <- '_dplyr_var'
45+
mad <- group_by_(data.frame(x=vals,w=windows), 'w') %>% mutate_(mad='sensorQC:::MAD.values(x)') %>% .$mad
46+
return(mad)
47+
}
48+
49+
2250
}
2351
#'@title median absolute deviation outlier test
52+
#'
53+
#' @description Median Absolute Deviation test
54+
#'
2455
#'@name MAD
2556
#'@aliases MAD
2657
#'@aliases median.absolute.deviation
@@ -29,6 +60,7 @@ MAD.windowed <- function(vals, windows){
2960
#'@return a vector of MAD normalized values relative to an undefined rejection criteria (usually 2.5 or 3).
3061
#'@keywords MAD
3162
#'@importFrom dplyr group_by_ mutate_ %>%
63+
#' @importFrom RcppRoll roll_median
3264
#'@author
3365
#'Jordan S. Read
3466
#'@export

R/window.R

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,20 @@ window.sensor<- function(x, ..., type){
2222

2323
if (type=='auto'){
2424
windowed.data <- auto.chunk.time(x$sensor)
25+
} else if (type=='rolling') {
26+
windowed.data <- rolling.window(x$sensor, ...)
2527
} else {
2628
windowed.data <- manual.chunk.time(x$sensor, type = type)
2729
}
2830

2931
return(sensor(windowed.data))
3032
}
3133

34+
rolling.window <- function(data.in, n){
35+
data.in$w <- rep(n, nrow(data.in))
36+
return(data.in)
37+
}
38+
3239
#' @importFrom stats window
3340
auto.chunk.time <- function(data.in){
3441

README.Rmd

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,14 @@ clean(data, 'x > 9999', 'persist(x) > 10', 'MAD(x) > 3', replace=NA)
9696
```
9797

9898

99+
#### flagging data with a moving window
100+
The `MAD(x,w)` function can use a rolling window by leveraging the `RcppRoll` R package.
101+
102+
```{r}
103+
sensor <- read(file, format="wide_burst", date.format="%m/%d/%Y %H:%M")
104+
sensor = window(sensor, n=300, type='rolling')
105+
flag(sensor, 'x == 999999', 'persist(x) > 3', 'MAD(x,w) > 3', 'MAD(x) > 3')
106+
```
107+
108+
109+

README.md

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ This package is still very much in development, so the API may change at any tim
2525

2626
High-frequency aquatic sensor QAQC procedures. `sensorQC` imports data, and runs various statistical outlier detection techniques as specified by the user.
2727

28-
### `sensorQC` Functions (as of v0.3.3)
28+
### `sensorQC` Functions (as of v0.4.0)
2929

3030
| Function | Title |
3131
|----------|:-------------------------------------------------------|
@@ -226,3 +226,44 @@ clean(data, 'x > 9999', 'persist(x) > 10', 'MAD(x) > 3', replace=NA)
226226
## 6 2
227227
## 7 3
228228
## 8 4
229+
230+
#### flagging data with a moving window
231+
232+
The `MAD(x,w)` function can use a rolling window by leveraging the `RcppRoll` R package.
233+
234+
``` r
235+
sensor <- read(file, format="wide_burst", date.format="%m/%d/%Y %H:%M")
236+
```
237+
238+
## number of observations:5100
239+
240+
``` r
241+
sensor = window(sensor, n=300, type='rolling')
242+
flag(sensor, 'x == 999999', 'persist(x) > 3', 'MAD(x,w) > 3', 'MAD(x) > 3')
243+
```
244+
245+
## Warning in MAD.roller(x, w): MAD.roller function has not been robustly
246+
## tested w/ NAs
247+
248+
## object of class "sensor"
249+
## times x
250+
## 1 2013-11-01 00:00:00 48.86
251+
## 2 2013-11-01 00:00:01 49.04
252+
## 3 2013-11-01 00:00:02 49.50
253+
## 4 2013-11-01 00:00:03 48.91
254+
## 5 2013-11-01 00:00:04 48.90
255+
## 6 2013-11-01 00:00:05 48.96
256+
## 7 2013-11-01 00:00:06 48.48
257+
## 8 2013-11-01 00:00:07 48.97
258+
## 9 2013-11-01 00:00:08 48.97
259+
## 10 2013-11-01 00:00:09 48.99
260+
## 11 2013-11-01 00:00:10 48.35
261+
## 12 2013-11-01 00:00:11 48.51
262+
## 13 2013-11-01 00:00:12 49.25
263+
## 14 2013-11-01 00:00:13 48.82
264+
## 15 2013-11-01 00:00:14 49.22
265+
## ...
266+
## x == 999999 (15 flags)
267+
## persist(x) > 3 (4 flags)
268+
## MAD(x,w) > 3 (187 flags)
269+
## MAD(x) > 3 (91 flags)

man/MAD.Rd

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/clean.Rd

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/flag.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/persist.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)