1
0
派生 0
镜像自地址 https://github.com/sensebox/opensensmapr 已同步 2025-09-20 00:32:34 +02:00

比较提交

...

2 提交

作者 SHA1 备注 提交日期
jan
b1001b174e improved runtime to be affordable on CRAN submission 2023-02-24 12:11:32 +01:00
jan
e2e9e3dbb3 automatically generated manual updates 2023-02-24 12:10:20 +01:00
共有 12 个文件被更改,包括 58 次插入50 次删除

查看文件

@ -1,6 +1,6 @@
Package: opensensmapr Package: opensensmapr
Type: Package Type: Package
Title: Client for the Data API of openSenseMap.org Title: Client for the Data API of 'openSenseMap.org'
Version: 0.6.0 Version: 0.6.0
URL: https://github.com/sensebox/opensensmapR URL: https://github.com/sensebox/opensensmapR
BugReports: https://github.com/sensebox/opensensmapR/issues BugReports: https://github.com/sensebox/opensensmapR/issues

查看文件

@ -4,7 +4,7 @@
\alias{filter.osem_measurements} \alias{filter.osem_measurements}
\title{Return rows with matching conditions, while maintaining class & attributes} \title{Return rows with matching conditions, while maintaining class & attributes}
\usage{ \usage{
filter.osem_measurements(.data, ..., .dots) \method{filter}{osem_measurements}(.data, ..., .dots)
} }
\arguments{ \arguments{
\item{.data}{A osem_measurements data.frame to filter} \item{.data}{A osem_measurements data.frame to filter}

查看文件

@ -4,7 +4,7 @@
\alias{filter.sensebox} \alias{filter.sensebox}
\title{Return rows with matching conditions, while maintaining class & attributes} \title{Return rows with matching conditions, while maintaining class & attributes}
\usage{ \usage{
filter.sensebox(.data, ..., .dots) \method{filter}{sensebox}(.data, ..., .dots)
} }
\arguments{ \arguments{
\item{.data}{A sensebox data.frame to filter} \item{.data}{A sensebox data.frame to filter}

查看文件

@ -4,7 +4,7 @@
\alias{mutate.osem_measurements} \alias{mutate.osem_measurements}
\title{Add new variables to the data, while maintaining class & attributes} \title{Add new variables to the data, while maintaining class & attributes}
\usage{ \usage{
mutate.osem_measurements(.data, ..., .dots) \method{mutate}{osem_measurements}(.data, ..., .dots)
} }
\arguments{ \arguments{
\item{.data}{A osem_measurements data.frame to mutate} \item{.data}{A osem_measurements data.frame to mutate}

查看文件

@ -4,7 +4,7 @@
\alias{mutate.sensebox} \alias{mutate.sensebox}
\title{Add new variables to the data, while maintaining class & attributes} \title{Add new variables to the data, while maintaining class & attributes}
\usage{ \usage{
mutate.sensebox(.data, ..., .dots) \method{mutate}{sensebox}(.data, ..., .dots)
} }
\arguments{ \arguments{
\item{.data}{A sensebox data.frame to mutate} \item{.data}{A sensebox data.frame to mutate}

查看文件

@ -4,7 +4,7 @@
\alias{st_as_sf.osem_measurements} \alias{st_as_sf.osem_measurements}
\title{Convert a \code{osem_measurements} dataframe to an \code{\link[sf]{st_sf}} object.} \title{Convert a \code{osem_measurements} dataframe to an \code{\link[sf]{st_sf}} object.}
\usage{ \usage{
st_as_sf.osem_measurements(x, ...) \method{st_as_sf}{osem_measurements}(x, ...)
} }
\arguments{ \arguments{
\item{x}{The object to convert} \item{x}{The object to convert}

查看文件

@ -4,7 +4,7 @@
\alias{st_as_sf.sensebox} \alias{st_as_sf.sensebox}
\title{Convert a \code{sensebox} dataframe to an \code{\link[sf]{st_sf}} object.} \title{Convert a \code{sensebox} dataframe to an \code{\link[sf]{st_sf}} object.}
\usage{ \usage{
st_as_sf.sensebox(x, ...) \method{st_as_sf}{sensebox}(x, ...)
} }
\arguments{ \arguments{
\item{x}{The object to convert} \item{x}{The object to convert}

查看文件

@ -2,21 +2,9 @@ source('testhelpers.R')
context('box') context('box')
try({ try({
boxes = osem_boxes()
box = osem_box('57000b8745fd40c8196ad04c') box = osem_box('57000b8745fd40c8196ad04c')
}) })
test_that('a single box can be retrieved by ID', {
check_api()
box = osem_box(boxes$X_id[[1]])
expect_true('sensebox' %in% class(box))
expect_true('data.frame' %in% class(box))
expect_true(nrow(box) == 1)
expect_true(box$X_id == boxes$X_id[[1]])
expect_silent(osem_box(boxes$X_id[[1]]))
})
test_that('required box attributes are correctly parsed', { test_that('required box attributes are correctly parsed', {
check_api() check_api()
@ -61,11 +49,6 @@ test_that('unknown box throws', {
expect_error(osem_box('57000b8745fd40c800000000'), 'not found') expect_error(osem_box('57000b8745fd40c800000000'), 'not found')
}) })
test_that('[.sensebox maintains attributes', {
check_api()
expect_true(all(attributes(boxes[1:nrow(boxes), ]) %in% attributes(boxes)))
})
test_that("print.sensebox filters important attributes for a single box", { test_that("print.sensebox filters important attributes for a single box", {
check_api() check_api()

查看文件

@ -172,3 +172,44 @@ test_that('requests can be cached', {
osem_clear_cache() osem_clear_cache()
expect_length(list.files(tempdir(), pattern = 'osemcache\\..*\\.rds'), 0) expect_length(list.files(tempdir(), pattern = 'osemcache\\..*\\.rds'), 0)
}) })
context('single box from boxes')
test_that('a single box can be retrieved by ID', {
check_api()
box = osem_box(boxes$X_id[[1]])
expect_true('sensebox' %in% class(box))
expect_true('data.frame' %in% class(box))
expect_true(nrow(box) == 1)
expect_true(box$X_id == boxes$X_id[[1]])
expect_silent(osem_box(boxes$X_id[[1]]))
})
test_that('[.sensebox maintains attributes', {
check_api()
expect_true(all(attributes(boxes[1:nrow(boxes), ]) %in% attributes(boxes)))
})
context('measurements boxes')
test_that('measurements of specific boxes can be retrieved for one phenomenon and returns a measurements data.frame', {
check_api()
# fix for subsetting
class(boxes) = c('data.frame')
three_boxes = boxes[1:3, ]
class(boxes) = c('sensebox', 'data.frame')
three_boxes = osem_as_sensebox(three_boxes)
phens = names(osem_phenomena(three_boxes))
measurements = osem_measurements(x = three_boxes, phenomenon = phens[[1]])
expect_true(is.data.frame(measurements))
expect_true('osem_measurements' %in% class(measurements))
})
test_that('phenomenon is required when requesting measurements, error otherwise', {
check_api()
expect_error(osem_measurements(boxes), 'Parameter "phenomenon" is required')
})

查看文件

@ -1,9 +1,6 @@
source('testhelpers.R') source('testhelpers.R')
context('measurements') context('measurements')
try({
boxes = osem_boxes()
})
test_that('measurements can be retrieved for a phenomenon', { test_that('measurements can be retrieved for a phenomenon', {
check_api() check_api()
@ -47,20 +44,6 @@ test_that('measurements can be retrieved for a phenomenon and exposure', {
expect_equal(nrow(measurements), 0) expect_equal(nrow(measurements), 0)
}) })
test_that('measurements of specific boxes can be retrieved for one phenomenon and returns a measurements data.frame', {
check_api()
# fix for subsetting
class(boxes) = c('data.frame')
three_boxes = boxes[1:3, ]
class(boxes) = c('sensebox', 'data.frame')
three_boxes = osem_as_sensebox(three_boxes)
phens = names(osem_phenomena(three_boxes))
measurements = osem_measurements(x = three_boxes, phenomenon = phens[[1]])
expect_true(is.data.frame(measurements))
expect_true('osem_measurements' %in% class(measurements))
})
test_that('measurements can be retrieved for a bounding box', { test_that('measurements can be retrieved for a bounding box', {
check_api() check_api()
@ -105,7 +88,6 @@ test_that('phenomenon is required when requesting measurements, error otherwise'
check_api() check_api()
expect_error(osem_measurements()) expect_error(osem_measurements())
expect_error(osem_measurements(boxes), 'Parameter "phenomenon" is required')
sfc = sf::st_sfc(sf::st_linestring(x = matrix(data = c(7, 8, 50, 51), ncol = 2)), crs = 4326) sfc = sf::st_sfc(sf::st_linestring(x = matrix(data = c(7, 8, 50, 51), ncol = 2)), crs = 4326)
bbox = sf::st_bbox(sfc) bbox = sf::st_bbox(sfc)

查看文件

@ -115,7 +115,9 @@ berlin = st_point(c(13.4034, 52.5120)) %>%
st_transform(4326) %>% # the opensensemap expects WGS 84 st_transform(4326) %>% # the opensensemap expects WGS 84
st_bbox() st_bbox()
``` ```
```{r results = F}
Since the API takes quite long to response measurements, especially filtered on space and time, we do not run the following chunks for publication of the package on CRAN.
```{r results = F, eval=FALSE}
pm25 = osem_measurements( pm25 = osem_measurements(
berlin, berlin,
phenomenon = 'PM2.5', phenomenon = 'PM2.5',
@ -129,7 +131,7 @@ plot(pm25)
Now we can get started with actual spatiotemporal data analysis. Now we can get started with actual spatiotemporal data analysis.
First, lets mask the seemingly uncalibrated sensors: First, lets mask the seemingly uncalibrated sensors:
```{r} ```{r, eval=FALSE}
outliers = filter(pm25, value > 100)$sensorId outliers = filter(pm25, value > 100)$sensorId
bad_sensors = outliers[, drop = T] %>% levels() bad_sensors = outliers[, drop = T] %>% levels()
@ -138,13 +140,13 @@ pm25 = mutate(pm25, invalid = sensorId %in% bad_sensors)
Then plot the measuring locations, flagging the outliers: Then plot the measuring locations, flagging the outliers:
```{r} ```{r, eval=FALSE}
st_as_sf(pm25) %>% st_geometry() %>% plot(col = factor(pm25$invalid), axes = T) st_as_sf(pm25) %>% st_geometry() %>% plot(col = factor(pm25$invalid), axes = T)
``` ```
Removing these sensors yields a nicer time series plot: Removing these sensors yields a nicer time series plot:
```{r} ```{r, eval=FALSE}
pm25 %>% filter(invalid == FALSE) %>% plot() pm25 %>% filter(invalid == FALSE) %>% plot()
``` ```

查看文件

@ -71,7 +71,7 @@ osem_clear_cache(getwd()) # clears a custom cache
If you want to roll your own serialization method to support custom data formats, If you want to roll your own serialization method to support custom data formats,
here's how: here's how:
```{r data, results='hide'} ```{r data, results='hide', eval=FALSE}
# first get our example data: # first get our example data:
measurements = osem_measurements('Windgeschwindigkeit') measurements = osem_measurements('Windgeschwindigkeit')
``` ```
@ -79,7 +79,7 @@ measurements = osem_measurements('Windgeschwindigkeit')
If you are paranoid and worry about `.rds` files not being decodable anymore If you are paranoid and worry about `.rds` files not being decodable anymore
in the (distant) future, you could serialize to a plain text format such as JSON. in the (distant) future, you could serialize to a plain text format such as JSON.
This of course comes at the cost of storage space and performance. This of course comes at the cost of storage space and performance.
```{r serialize_json} ```{r serialize_json, eval=FALSE}
# serializing senseBoxes to JSON, and loading from file again: # serializing senseBoxes to JSON, and loading from file again:
write(jsonlite::serializeJSON(measurements), 'measurements.json') write(jsonlite::serializeJSON(measurements), 'measurements.json')
measurements_from_file = jsonlite::unserializeJSON(readr::read_file('measurements.json')) measurements_from_file = jsonlite::unserializeJSON(readr::read_file('measurements.json'))
@ -90,7 +90,7 @@ This method also persists the R object metadata (classes, attributes).
If you were to use a serialization method that can't persist object metadata, you If you were to use a serialization method that can't persist object metadata, you
could re-apply it with the following functions: could re-apply it with the following functions:
```{r serialize_attrs} ```{r serialize_attrs, eval=FALSE}
# note the toJSON call instead of serializeJSON # note the toJSON call instead of serializeJSON
write(jsonlite::toJSON(measurements), 'measurements_bad.json') write(jsonlite::toJSON(measurements), 'measurements_bad.json')
measurements_without_attrs = jsonlite::fromJSON('measurements_bad.json') measurements_without_attrs = jsonlite::fromJSON('measurements_bad.json')
@ -101,6 +101,6 @@ class(measurements_with_attrs)
``` ```
The same goes for boxes via `osem_as_sensebox()`. The same goes for boxes via `osem_as_sensebox()`.
```{r cleanup, include=FALSE} ```{r cleanup, include=FALSE, eval=FALSE}
file.remove('measurements.json', 'measurements_bad.json') file.remove('measurements.json', 'measurements_bad.json')
``` ```