10
10
# ' data frame or the \code{\link{stations_search}} function to find Climate
11
11
# ' IDs.
12
12
# ' @param normals_years Character. The year range for which you want climate
13
- # ' normals. Default "1981-2010".
13
+ # ' normals. Default "1981-2010". One of "1971-2000", "1981-2010", "1991-2020".
14
+ # ' Note: Some "1991-2020" are available online, but are not yet downloadable
15
+ # ' via weathercan.
14
16
# ' @param format Logical. If TRUE (default) formats measurements to numeric and
15
17
# ' date accordingly. Unlike `weather_dl()`, `normals_dl()` will always format
16
18
# ' column headings as normals data from ECCC cannot be directly made into a
29
31
# ' not the climate normals for this station met the WMO standards for
30
32
# ' temperature and precipitation (i.e. both have code >= A). Each measurement
31
33
# ' column has a corresponding `_code` column which reflects the data quality
32
- # ' of that measurement (see the [1981-2010 ECCC calculations
33
- # ' document](https://climate.weather.gc.ca/doc/Canadian_Climate_Normals_1981_2010_Calculation_Information.pdf)
34
- # ' or the [1971-2000 ECCC calculations document](https://climate.weather.gc.ca/doc/Canadian_Climate_Normals_1971_2000_Calculation_Information.pdf)
35
- # ' for more details)
34
+ # ' of that measurement (see the
35
+ # ' [1991-2020](https://collaboration.cmc.ec.gc.ca/cmc/climate/Normals/Canadian_Climate_Normals_1991_2020_Calculation_Information.pdf),
36
+ # ' [1981-2010](https://collaboration.cmc.ec.gc.ca/cmc/climate/Normals/Canadian_Climate_Normals_1981_2010_Calculation_Information.pdf), or
37
+ # ' [1971-2000](https://collaboration.cmc.ec.gc.ca/cmc/climate/Normals/Canadian_Climate_Normals_1971_2000_Calculation_Information.pdf)
38
+ # ' for more details) ECCC calculation documents.
36
39
# '
37
40
# ' Climate normals are downloaded from the url stored in option
38
41
# ' `weathercan.urls.normals`. To change this location use:
49
52
# ' n <- normals_dl(climate_ids = "5010480")
50
53
# ' n
51
54
# '
52
- # ' # Pull out last frost data
55
+ # ' # Pull out last frost data *with* station information
53
56
# ' library(tidyr)
54
57
# ' f <- unnest(n, frost)
55
58
# ' f
56
59
# '
57
- # ' # Pull out normals
60
+ # ' # Pull out normals *with* station information
58
61
# ' nm <- unnest(n, normals)
59
62
# ' nm
60
63
# '
67
70
# '
68
71
# ' # Download multiple stations for 1981-2010,
69
72
# ' n <- normals_dl(climate_ids = c("301C3D4", "301FFNJ", "301N49A"))
70
- # ' n
73
+ # ' unnest(n, frost)
74
+ # '
71
75
# '
72
- # ' # Note, putting both into the same data set can be done but makes for
76
+ # ' # Note, putting both normals and frost data into the same data set can be done but makes for
73
77
# ' # a very unweildly dataset (there is lots of repetition)
74
- # ' nm <- unnest(n, normals)
75
- # ' f <- unnest(n, frost)
76
- # ' both <- dplyr::full_join(nm, f)
77
- # ' both
78
+ # ' nm <- unnest(n, normals) |>
79
+ # ' unnest(frost)
78
80
# ' @export
79
81
80
82
normals_dl <- function (climate_ids , normals_years = " 1981-2010" ,
@@ -89,6 +91,11 @@ normals_dl <- function(climate_ids, normals_years = "1981-2010",
89
91
}
90
92
stn <- stations()
91
93
94
+ if (normals_years == " 1991-2020" ) {
95
+ stop(" The new normals for 1991-2020 are not yet available via weathercan" ,
96
+ call. = FALSE )
97
+ }
98
+
92
99
check_ids(climate_ids , stn , type = " climate_id" )
93
100
check_normals(normals_years )
94
101
@@ -111,7 +118,6 @@ normals_dl <- function(climate_ids, normals_years = "1981-2010",
111
118
dplyr :: select(- " normals" )
112
119
}
113
120
114
-
115
121
# Download data
116
122
n <- n %> %
117
123
dplyr :: mutate(
@@ -326,57 +332,66 @@ frost_extract <- function(f, climate_id) {
326
332
327
333
if (all(f == " " )) return (dplyr :: tibble())
328
334
329
- frost_free <- stringr :: str_which(f , f_names $ variable [f_names $ group == 1 ][1 ])
330
- frost_probs <- stringr :: str_which(f , f_names $ variable [f_names $ group == 2 ][1 ])
335
+ frost_free <- stringr :: str_which(f , f_names $ match [f_names $ group == 1 ][1 ])[ 1 ]
336
+ frost_probs <- stringr :: str_which(f , f_names $ match [f_names $ group == 2 ][1 ])[ 1 ]
331
337
332
338
# Frost free days overall
333
- if (length(frost_free ) > 0 ) {
339
+ if (any( ! is.na( frost_free )) && length(frost_free ) > 0 ) {
334
340
if (length(frost_probs ) == 0 ) last <- length(f ) else last <- frost_probs - 1
335
341
336
342
readr :: local_edition(1 )
337
343
f1 <- readr :: read_csv(I(f [frost_free : last ]),
338
344
col_names = c(" variable" , " value" , " frost_code" ),
339
- col_types = readr :: cols(), progress = FALSE ) % > %
345
+ col_types = readr :: cols(), progress = FALSE ) | >
340
346
tidyr :: spread(key = " variable" , value = " value" )
341
347
342
- n <- tibble_to_list(f_names [f_names $ variable %in% names(f1 ),
343
- c(" new_var" , " variable" )])
344
- f1 <- dplyr :: rename(f1 , !! n ) %> %
348
+ nms <- purrr :: map(stats :: setNames(f_names $ match , f_names $ new_var ),
349
+ \(x ) stringr :: str_subset(names(f1 ), x )) | >
350
+ unlist()
351
+
352
+ f1 <- dplyr :: rename(f1 , !! nms ) %> %
345
353
dplyr :: mutate_at(.vars = dplyr :: vars(dplyr :: contains(" date" )),
346
- ~ lubridate :: yday(lubridate :: as_date(paste0(" 1999" , . )))) % > %
354
+ ~ lubridate :: yday(lubridate :: as_date(paste0(" 1999" , . )))) | >
347
355
dplyr :: mutate(length_frost_free =
348
356
stringr :: str_extract(.data $ length_frost_free , " [0-9]*" ),
349
357
length_frost_free = as.numeric(.data $ length_frost_free ))
350
358
} else f1 <- na_tibble(f_names $ new_var [f_names $ group == 1 ])
351
359
352
360
# Frost free probabilities
353
- if (length(frost_probs ) > 0 ) {
361
+ if (any(! is.na(frost_probs )) && length(frost_probs ) > 0 ) {
362
+
354
363
readr :: local_edition(1 )
355
364
f2 <- readr :: read_csv(I(f [frost_probs : length(f )]),
356
365
col_names = FALSE , col_types = readr :: cols(),
357
- progress = FALSE ) %> %
358
- as.data.frame()
359
- f2 <- data.frame (prob = rep(c(" 10%" , " 25%" , " 33%" , " 50%" ,
360
- " 66%" , " 75%" , " 90%" ), 3 ),
361
- value = c(t(f2 [2 , 2 : 8 ]), t(f2 [4 , 2 : 8 ]), t(f2 [6 , 2 : 8 ])),
362
- measure = c(rep(f2 [1 ,1 ], 7 ), rep(f2 [3 ,1 ], 7 ),
363
- rep(f2 [5 ,1 ], 7 ))) %> %
364
- tidyr :: spread(" measure" , " value" )
365
-
366
- n <- tibble_to_list(f_names [f_names $ variable %in% names(f2 ),
367
- c(" new_var" , " variable" )])
368
-
369
- f2 <- dplyr :: rename(f2 , !! n )
366
+ progress = FALSE ) | >
367
+ dplyr :: select(dplyr :: where(\(x ) ! all(is.na(x )))) | >
368
+ dplyr :: rename_with(
369
+ .fn = \(x ) " prob" ,
370
+ .cols = dplyr :: where(\(x ) any(stringr :: str_detect(x , " (P|p)robability" )))) | >
371
+ dplyr :: rename_with(
372
+ .fn = \(x ) " value" ,
373
+ .cols = dplyr :: where(\(x ) {
374
+ any(stringr :: str_detect(x , paste0(" (" , paste0(month.abb , collapse = " )|(" ), " )" )))
375
+ })) | >
376
+ dplyr :: mutate(measure = stringr :: str_remove(.data $ prob , " \\ (\\ d{2}%\\ )" ),
377
+ prob = stringr :: str_extract(.data $ prob , " \\ d{2}%" )) | >
378
+ tidyr :: pivot_wider(names_from = " measure" , values_from = " value" )
379
+
380
+ nms <- purrr :: map(stats :: setNames(f_names $ match , f_names $ new_var ),
381
+ \(x ) stringr :: str_subset(names(f2 ), x )) | >
382
+ unlist()
383
+
384
+ f2 <- dplyr :: rename(f2 , !! nms )
370
385
} else f2 <- na_tibble(f_names $ new_var [f_names $ group == 2 ])
371
386
372
387
if (nrow(f1 ) == 0 & nrow(f2 ) == 0 ) {
373
388
r <- cbind(f1 , f2 )
374
389
} else {
375
390
r <- dplyr :: full_join(
376
- dplyr :: mutate(f1 , climate_id = climate_id ),
377
- dplyr :: mutate(f2 , climate_id = climate_id ),
378
- by = " climate_id" , relationship = " many-to-many" ) % > %
379
- dplyr :: select(- climate_id )
391
+ dplyr :: mutate(f1 , climate_id = .env $ climate_id ),
392
+ dplyr :: mutate(f2 , climate_id = .env $ climate_id ),
393
+ by = " climate_id" , relationship = " many-to-many" ) | >
394
+ dplyr :: select(- " climate_id" )
380
395
}
381
396
382
397
dplyr :: as_tibble(r )
@@ -389,18 +404,20 @@ frost_find <- function(n, type = "extract") {
389
404
# If no frost-free title, look for next measurement
390
405
391
406
if (length(frost ) == 0 ) {
392
- for (i in f_names $ variable ) {
393
- frost <- find_line(n , i )
394
- if (length(frost ) != 0 ) break
395
- }
407
+ frost <- purrr :: map(f_names $ match , \(x ) find_line(n , x )) | >
408
+ unlist() | >
409
+ min_na()
396
410
}
397
411
398
412
if (length(frost ) == 1 ) {
399
413
if (type == " extract" ) r <- n [(frost ): length(n )]
400
414
if (type == " remove" ) r <- n [1 : (frost - 1 )]
401
- } else {
415
+ } else if (length( frost ) == 0 ) {
402
416
if (type == " extract" ) r <- " "
403
417
if (type == " remove" ) r <- n
418
+ } else {
419
+ stop(" Problem identifying frost data in normals\n Please report this here: " ,
420
+ " https://github.com/ropensci/weathercan/issues" , call. = FALSE )
404
421
}
405
422
r
406
423
}
0 commit comments