Skip to content

Commit fe2867b

Browse files
committed
Merge branch 'master' into WRB2022
2 parents e95198f + 6c095c4 commit fe2867b

25 files changed

+340
-109
lines changed

.github/workflows/R-CMD-check.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,21 @@ jobs:
2626
- {os: macOS-latest, r: 'release'}
2727
- {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
2828
- {os: ubuntu-22.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/jammy/latest"}
29-
- {os: ubuntu-20.04, r: '3.5', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
29+
- {os: ubuntu-20.04, r: '3.6', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
3030

3131
env:
3232
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
3333
RSPM: ${{ matrix.config.rspm }}
3434
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
3535

3636
steps:
37-
- uses: actions/checkout@v2
37+
- uses: actions/checkout@v4
3838

3939
- uses: r-lib/actions/setup-r@v2
4040
with:
4141
r-version: ${{ matrix.config.r }}
4242

43-
- uses: r-lib/actions/setup-pandoc@v1
43+
- uses: r-lib/actions/setup-pandoc@v2
4444

4545
- name: Query dependencies
4646
run: |

DESCRIPTION

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Title: A System of Soil Classification for Making and Interpreting Soil Surveys
33
Description: Taxonomic dictionaries, formative element lists, and functions related to the maintenance, development and application of U.S. Soil Taxonomy.
44
Data and functionality are based on official U.S. Department of Agriculture sources including the latest edition of the Keys to Soil Taxonomy. Descriptions and metadata are obtained from the National Soil Information System or Soil Survey Geographic databases. Other sources are referenced in the data documentation.
55
Provides tools for understanding and interacting with concepts in the U.S. Soil Taxonomic System. Most of the current utilities are for working with taxonomic concepts at the "higher" taxonomic levels: Order, Suborder, Great Group, and Subgroup.
6-
Version: 0.2.3
6+
Version: 0.2.5
77
Authors@R: c(person(given="Andrew", family="Brown", email="[email protected]", role = c("aut", "cre")), person(given="Dylan", family="Beaudette", role = c("aut"), email = "[email protected]"))
88
Maintainer: Andrew Brown <[email protected]>
99
Depends: R (>= 3.5)

NAMESPACE

+1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ importFrom(stringr,fixed)
4242
importFrom(stringr,str_locate)
4343
importFrom(stringr,str_locate_all)
4444
importFrom(utils,browseURL)
45+
importFrom(utils,tail)
4546
importFrom(utils,type.convert)

NEWS.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# SoilTaxonomy 0.2.4 (2023-11-16)
2+
- `taxonTree()` default markup via `special.chars` argument emulates `fs::dir_tree()` output
3+
- `parse_family()` now returns more complete information for taxa above family
4+
- `taxminalogy` column for taxa with strongly contrasting control sections now use `" over "` as the separator between class names.
5+
16
# SoilTaxonomy 0.2.3 (2023-02-01)
27
- Fix unintended case-sensitivity of `FormativeElements()`; thanks to Shawn Salley (@swsalley)
38
- Fix for `extractSMR()` via fix for `FormativeElements()` applied at multiple levels (affects taxa above subgroup level)

R/explainST.R

+40-33
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#' Explain a taxon name using formative elements
1+
#' @title Explain a taxon name using formative elements
22
#'
33
#' @param x a Subgroup, Great Group, Suborder or Order-level taxonomic name; matching is exact and case-insensitive
44
#' @param format output format: 'text' | 'html'
@@ -27,9 +27,16 @@ explainST <- function(x, format = c('text', 'html'), viewer = TRUE) {
2727
x.lvl <- taxon_to_level(x)
2828

2929
# no-match NULL data object
30-
empty <- list(defs = data.frame(element = "", derivation = "",
31-
connotation = "", simplified = NA, link = NA),
32-
char.index = 0)
30+
empty <- list(
31+
defs = data.frame(
32+
element = "",
33+
derivation = "",
34+
connotation = "",
35+
simplified = NA,
36+
link = NA
37+
),
38+
char.index = 0
39+
)
3340

3441
if (!is.na(x.lvl) && x.lvl == "order") {
3542
# handle input of full order name e.g. "aridisols"
@@ -63,11 +70,11 @@ explainST <- function(x, format = c('text', 'html'), viewer = TRUE) {
6370
} else {
6471
x.sg <- empty
6572
}
66-
73+
6774
# TODO: family classes
6875

69-
newline <- switch(format, text='\n', html='<br>')
70-
whitespace <- switch(format, text=' ', html='&nbsp;')
76+
newline <- switch(format, text = '\n', html = '<br>')
77+
whitespace <- switch(format, text = ' ', html = '&nbsp;')
7178

7279
main.style <- 'font-size: 85%; font-weight: bold;'
7380
sub.style <- 'font-size: 85%; font-style: italic;'
@@ -81,10 +88,10 @@ explainST <- function(x, format = c('text', 'html'), viewer = TRUE) {
8188
if(format == 'html') {
8289
#
8390
x.txt <- paste0('<html><div style="padding: 5px; font-family: monospace; border: 1px solid grey; border-radius: 5px;">',
84-
'<span style="', main.style, '">',
85-
x,
86-
'</span>'
87-
)
91+
'<span style="', main.style, '">',
92+
x,
93+
'</span>'
94+
)
8895

8996
sg.txt <- paste0('<span style="', sub.style, '">', sg.l, '</span>')
9097
gg.txt <- paste0('<span style="', sub.style, '">', gg.l, '</span>')
@@ -105,16 +112,16 @@ explainST <- function(x, format = c('text', 'html'), viewer = TRUE) {
105112
# the taxon to explain, usually a subgroup
106113
ex <- append(ex, x.txt)
107114

108-
if (grepl("[A-Za-z?]", gsub("&nbsp;"," ",sg.l[[2]])))
115+
if (grepl("[A-Za-z?]", gsub("&nbsp;"," ", sg.l[[2]])))
109116
ex <- append(ex, sg.txt)
110117

111-
if (grepl("[A-Za-z?]", gsub("&nbsp;"," ",gg.l[[2]])))
118+
if (grepl("[A-Za-z?]", gsub("&nbsp;"," ", gg.l[[2]])))
112119
ex <- append(ex, gg.txt)
113120

114-
if (grepl("[A-Za-z?]", gsub("&nbsp;"," ",so.l[[2]])))
121+
if (grepl("[A-Za-z?]", gsub("&nbsp;"," ", so.l[[2]])))
115122
ex <- append(ex, so.txt)
116123

117-
if (grepl("[A-Za-z?]", gsub("&nbsp;"," ",o.l[[2]])))
124+
if (grepl("[A-Za-z?]", gsub("&nbsp;"," ", o.l[[2]])))
118125
ex <- append(ex, o.txt)
119126

120127
if(format == 'html') {
@@ -126,13 +133,13 @@ explainST <- function(x, format = c('text', 'html'), viewer = TRUE) {
126133
ex.char <- unlist(ex, recursive = TRUE)
127134

128135
# collapse to single character
129-
res <- paste(ex.char, collapse=newline)
136+
res <- paste(ex.char, collapse = newline)
130137

131138
# put HTML output into viewer
132139
if(format == 'html' && viewer) {
133140
viewer <- getOption("viewer", default = utils::browseURL)
134-
tf <- tempfile(fileext=".html")
135-
cat(res, file=tf)
141+
tf <- tempfile(fileext = ".html")
142+
cat(res, file = tf)
136143
viewer(tf)
137144
}
138145

@@ -147,7 +154,7 @@ explainST <- function(x, format = c('text', 'html'), viewer = TRUE) {
147154

148155
## TODO: wrap-text with newline if > width
149156

150-
.printExplanation <- function(pos, txt, width=100, ws.char=' ') {
157+
.printExplanation <- function(pos, txt, width = 100, ws.char = ' ') {
151158

152159
# convert factor to character if txt is factor
153160
txt <- as.character(txt)
@@ -156,53 +163,53 @@ explainST <- function(x, format = c('text', 'html'), viewer = TRUE) {
156163
# split explanation into a vector
157164
txt <- strsplit(txt, split = '')[[1]]
158165
# placement of explanation
159-
idx <- seq(from=pos, to=pos + (length(txt) - 1))
166+
idx <- seq(from = pos, to = pos + (length(txt) - 1))
160167
# init whitespace, making room for very long explanation
161-
ws <- rep(ws.char, times=pmax(width, max(idx)))
168+
ws <- rep(ws.char, times = pmax(width, max(idx)))
162169
# insert text
163170
ws[idx] <- txt
164171
} else {
165172
return("")
166173
}
167174
# convert to character
168-
return(paste(ws, collapse=''))
175+
return(paste(ws, collapse = ''))
169176
}
170177

171-
.makeBars <- function(width=100, pos, ws.char=' ') {
178+
.makeBars <- function(width = 100, pos, ws.char = ' ') {
172179
# init whitespace
173-
ws <- rep(ws.char, times=width)
180+
ws <- rep(ws.char, times = width)
174181
# insert bars
175182
ws[pos] <- '|'
176183

177184
# convert to character
178-
return(paste(ws, collapse=''))
185+
return(paste(ws, collapse = ''))
179186
}
180187

181188

182189

183190
.soilOrderLines <- function(o, ws) {
184191
txt <- list()
185192

186-
txt[[1]] <- .makeBars(pos=o$char.index, ws.char=ws)
187-
txt[[2]] <- .printExplanation(pos = o$char.index, txt = o$defs$connotation, ws.char=ws)
193+
txt[[1]] <- .makeBars(pos = o$char.index, ws.char = ws)
194+
txt[[2]] <- .printExplanation(pos = o$char.index, txt = o$defs$connotation, ws.char = ws)
188195

189196
return(txt)
190197
}
191198

192199
.subOrderLines <- function(o, so, ws) {
193200
txt <- list()
194201

195-
txt[[1]] <- .makeBars(pos=c(so$char.index, o$char.index), ws.char=ws)
196-
txt[[2]] <- .printExplanation(pos = so$char.index, txt = so$defs$connotation, ws.char=ws)
202+
txt[[1]] <- .makeBars(pos = c(so$char.index, o$char.index), ws.char = ws)
203+
txt[[2]] <- .printExplanation(pos = so$char.index, txt = so$defs$connotation, ws.char = ws)
197204

198205
return(txt)
199206
}
200207

201208
.greatGroupLines <- function(o, so, gg, ws) {
202209
txt <- list()
203210

204-
txt[[1]] <- .makeBars(pos=c(gg$char.index, so$char.index, o$char.index), ws.char=ws)
205-
txt[[2]] <- .printExplanation(pos = gg$char.index, txt = gg$defs$connotation, ws.char=ws)
211+
txt[[1]] <- .makeBars(pos = c(gg$char.index, so$char.index, o$char.index), ws.char = ws)
212+
txt[[2]] <- .printExplanation(pos = gg$char.index, txt = gg$defs$connotation, ws.char = ws)
206213

207214
return(txt)
208215
}
@@ -230,8 +237,8 @@ explainST <- function(x, format = c('text', 'html'), viewer = TRUE) {
230237
while(i < length(sg.pos)+1) {
231238

232239
# add all bars
233-
txt[[j]] <- .makeBars(pos=c(sg.pos.temp, gg$char.index, so$char.index, o$char.index), ws.char=ws)
234-
txt[[j+1]] <- .printExplanation(pos = sg.pos.temp[1], txt = sg.defs[1], ws.char=ws)
240+
txt[[j]] <- .makeBars(pos = c(sg.pos.temp, gg$char.index, so$char.index, o$char.index), ws.char = ws)
241+
txt[[j+1]] <- .printExplanation(pos = sg.pos.temp[1], txt = sg.defs[1], ws.char = ws)
235242

236243
# nibble vectors
237244
sg.pos.temp <- sg.pos.temp[-1]

R/family-classes.R

+23-15
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ parse_family <- function(family, column_metadata = TRUE, flat = TRUE) {
3030
# load local copy of taxon code lookup table
3131
load(system.file("data/ST_unique_list.rda", package = "SoilTaxonomy")[1])
3232

33-
lut <- ST_unique_list[["subgroup"]]
33+
lut <- do.call('c', ST_unique_list)
3434

3535
# lookup table sorted from largest to smallest (most specific to least)
3636
lut <- lut[order(nchar(lut), decreasing = TRUE)]
@@ -40,13 +40,16 @@ parse_family <- function(family, column_metadata = TRUE, flat = TRUE) {
4040
subgroup.idx <- sapply(res, function(x) which(!is.na(x[,1]))[1])
4141
subgroup.pos <- sapply(seq_along(subgroup.idx), function(i) res[[i]][subgroup.idx[i], 'start'])
4242

43-
subgroups <- lut[subgroup.idx]
43+
taxname <- lut[subgroup.idx]
44+
lowest_level <- taxon_to_level(taxname)
4445
family_classes <- trimws(substr(family, 0, subgroup.pos - 1))
45-
46+
taxon_codes <- taxon_to_taxon_code(taxname)
4647
res <- data.frame(row.names = NULL, stringsAsFactors = FALSE,
47-
family = family,
48-
subgroup = subgroups,
49-
subgroup_code = taxon_to_taxon_code(subgroups),
48+
family = ifelse(nchar(family_classes) > 0, family, NA_character_),
49+
taxclname = family,
50+
taxonname = taxname,
51+
subgroup_code = ifelse(lowest_level == "subgroup", taxon_codes, NA_character_),
52+
code = taxon_codes,
5053
class_string = family_classes,
5154
classes_split = I(lapply(strsplit(family_classes, ","), trimws)))
5255

@@ -56,7 +59,7 @@ parse_family <- function(family, column_metadata = TRUE, flat = TRUE) {
5659
}
5760

5861
#' @import data.table
59-
#' @importFrom utils type.convert
62+
#' @importFrom utils type.convert tail
6063
#' @importFrom stats setNames na.omit
6164
.get_family_differentiae <- function(res, flat = TRUE) {
6265

@@ -125,10 +128,14 @@ parse_family <- function(family, column_metadata = TRUE, flat = TRUE) {
125128
)
126129
})
127130

128-
taxsub <- as.data.frame(do.call('rbind', lapply(decompose_taxon_code(res$subgroup_code), function(x) taxon_code_to_taxon(as.character(rev(x))))),
129-
stringsAsFactors = FALSE)
130-
colnames(taxsub) <- rev(c("taxorder", "taxsuborder", "taxgrtgroup", "taxsubgrp"))
131-
rownames(taxsub) <- NULL
131+
taxsub <- as.data.frame(data.table::rbindlist(lapply(decompose_taxon_code(res$code), function(x) {
132+
y <- taxon_code_to_taxon(as.character(rev(x)))
133+
z <- data.frame(taxsubgrp = NA_character_, taxgrtgroup = NA_character_,
134+
taxsuborder = NA_character_, taxorder = NA_character_,
135+
stringsAsFactors = FALSE)
136+
z[1, ] <- tail(c(rep(NA_character_, 4), y), 4)
137+
z
138+
})), stringsAsFactors = FALSE)
132139

133140
res4 <- lapply(seq_along(res2), function(i) {
134141
x <- res2[[i]]
@@ -160,9 +167,9 @@ parse_family <- function(family, column_metadata = TRUE, flat = TRUE) {
160167

161168
res5 <- as.list(data.table::rbindlist(c(list(basetbl), res4), fill = TRUE))
162169
multi.names <- c("taxminalogy", "taxfamother")
163-
.FUN <- function(x) list(x)
164-
.flat_FUN <- function(x) {
165-
y <- paste0(na.omit(x), collapse = ", ")
170+
.FUN <- function(x, sep = NULL) list(x)
171+
.flat_FUN <- function(x, sep = ", ") {
172+
y <- paste0(na.omit(x), collapse = sep)
166173
if (nchar(y) == 0) return(NA_character_)
167174
y
168175
}
@@ -171,7 +178,8 @@ parse_family <- function(family, column_metadata = TRUE, flat = TRUE) {
171178
}
172179

173180
res5[multi.names] <- lapply(multi.names, function(n) {
174-
res6 <- apply(data.frame(res5[names(res5) %in% n]), 1, .FUN)
181+
res6 <- apply(data.frame(res5[names(res5) %in% n]), 1, .FUN,
182+
sep = ifelse(n == "taxminalogy", " over ", ", "))
175183
res6 <- lapply(res6, function(nn) {
176184
nnn <- nn[[1]]
177185
lr6 <- length(nnn)

data-raw/package-datasets.R

+8-5
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ ST_higher_taxa_codes_13th <- jsonlite::fromJSON("https://raw.githubusercontent.c
7474
colnames(ST_higher_taxa_codes_13th) <- c("code", "taxon")
7575
usethis::use_data(ST_higher_taxa_codes_13th, overwrite = TRUE)
7676

77-
latest_taxa <- ST_higher_taxa_codes_13th
77+
ST_higher_taxa_codes_12th <- jsonlite::fromJSON("https://raw.githubusercontent.com/ncss-tech/SoilKnowledgeBase/main/inst/extdata/KST/2014_KST_codes.json")
78+
colnames(ST_higher_taxa_codes_12th) <- c("code", "taxon")
79+
usethis::use_data(ST_higher_taxa_codes_12th, overwrite = TRUE)
80+
81+
latest_taxa <- ST_higher_taxa_codes_12th
7882

7983
# re-arrange taxa according to letter codes in the 'Keys
8084
.uniqueTaxaLogicalOrdering <- function(x) {
@@ -104,18 +108,17 @@ usethis::use_data(ST_unique_list, overwrite = TRUE)
104108
## formative element dictionaries
105109
load('misc/formative-elements/formative-elements.rda')
106110
ST_formative_elements <- ST.formative_elements
107-
names(ST_formative_elements) <- c("order","suborder","greatgroup","subgroup")
111+
names(ST_formative_elements) <- c("order", "suborder", "greatgroup", "subgroup")
108112

109113
# find formative elements in order names and add to table
110114
y <- ST_formative_elements[["order"]]
111115
res <- data.frame(y$order, stringr::str_locate(y$order, gsub("(.*)s$","\\1", y$element)))
112-
colnames(res) <- c("order","element_start","element_end")
116+
colnames(res) <- c("order", "element_start", "element_end")
113117
ST_formative_elements[["order"]] <- merge(ST_formative_elements[["order"]], res, by = "order")
114118

115119
usethis::use_data(ST_formative_elements, overwrite = TRUE)
116120

117-
ST_feature_SKB <- jsonlite::read_json("https://github.com/ncss-tech/SoilKnowledgeBase/raw/main/inst/extdata/KST/2014_KST_EN_featurelist.json",
118-
simplifyVector = TRUE)
121+
ST_feature_SKB <- jsonlite::read_json("https://github.com/ncss-tech/SoilKnowledgeBase/raw/main/inst/extdata/KST/2014_KST_EN_featurelist.json", simplifyVector = TRUE)
119122

120123
# handle marked UTF8 strings
121124
ST_feature_SKB$description <- sapply(ST_feature_SKB$description, stringi::stri_enc_toascii)

data/ST.rda

31 Bytes
Binary file not shown.

data/ST_family_classes.rda

-4 Bytes
Binary file not shown.

data/ST_features.rda

-8 Bytes
Binary file not shown.

data/ST_formative_elements.rda

55 Bytes
Binary file not shown.

data/ST_higher_taxa_codes_12th.rda

-5.57 KB
Binary file not shown.

data/ST_higher_taxa_codes_13th.rda

-107 Bytes
Binary file not shown.

data/ST_unique_list.rda

-14 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)