| Title: | Visualize and Report Soil Health Data |
|---|---|
| Description: | Collection of soil health data visualization and reporting tools, including a RStudio project template with everything you need to generate custom HTML and Microsoft Word reports for each participant in your soil health sampling project. |
| Authors: | Jadey N Ryan [cre, aut] (ORCID: <https://orcid.org/0009-0004-5998-4697>), Molly McIlquham [aut] (ORCID: <https://orcid.org/0000-0002-0152-969X>), Kwabena A Sarpong [aut], Leslie M Michel [aut], Teal S Potter [aut] (ORCID: <https://orcid.org/0000-0002-4884-2720>), Deirdre Griffin LaHue [aut] (ORCID: <https://orcid.org/0000-0001-5711-797X>), Dani L Gelardi [aut] (ORCID: <https://orcid.org/0000-0002-5015-8119>), Washington State Department of Agriculture [cph, fnd] |
| Maintainer: | Jadey N Ryan <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 1.0.1.9000 |
| Built: | 2026-06-02 08:31:19 UTC |
| Source: | https://github.com/WA-Department-of-Agriculture/soils |
Adds a footnote explaining that field counts reflect the total number of samples in the crop/county/project group, and that some measurements may be based on fewer samples if results were not available for all fields.
add_field_count_note(ft, language = "English")add_field_count_note(ft, language = "English")
ft |
A flextable object |
language |
"English" (default) or "Spanish" |
Add a legend to the texture triangle
add_legend( x = 1, y = 0.7, box = FALSE, legend = c("Your fields", "Same county", "Same crop", "Other fields"), color = c("#a60f2dCC", "#3E3D3D99", "#3E3D3D99", "#ccc29c80"), pch = c(15, 17, 18, 19), size = c(2.4, 2.16, 2.16, 1.36), vertical_spacing = 1.5, ... )add_legend( x = 1, y = 0.7, box = FALSE, legend = c("Your fields", "Same county", "Same crop", "Other fields"), color = c("#a60f2dCC", "#3E3D3D99", "#3E3D3D99", "#ccc29c80"), pch = c(15, 17, 18, 19), size = c(2.4, 2.16, 2.16, 1.36), vertical_spacing = 1.5, ... )
x, y
|
X and Y coordinates used to position the legend. Location may also
be specified by setting |
box |
Boolean. |
legend |
Character vector to appear in legend. |
color |
Character vector of the color of the points. |
pch |
Numeric vector of plotting symbols. See |
size |
Numeric expansion factor for points. |
vertical_spacing |
Numeric spacing factor for vertical line distances between each legend item. |
... |
Other arguments passed to |
A list with list components for the legend's box and legend's text(s).
texture <- washi_data |> dplyr::select( sand = sand_percent, silt = silt_percent, clay = clay_percent ) make_texture_triangle(body_font = "sans") # Add gray points add_texture_points( tail(texture, 5), color = "#3E3D3D90", pch = 19 ) # Add red points add_texture_points( head(texture, 5), color = "#a60f2dCC", pch = 15 ) # Add legend add_legend( legend = c("Red squares", "Gray circles"), color = c("#a60f2dCC", "#3E3D3D90"), pch = c(15, 19), vertical_spacing = 2 ) # Note the text appears squished in this example since the width, height, # and resolution have been optimized to print the figure 6 in wide in the # report.texture <- washi_data |> dplyr::select( sand = sand_percent, silt = silt_percent, clay = clay_percent ) make_texture_triangle(body_font = "sans") # Add gray points add_texture_points( tail(texture, 5), color = "#3E3D3D90", pch = 19 ) # Add red points add_texture_points( head(texture, 5), color = "#a60f2dCC", pch = 15 ) # Add legend add_legend( legend = c("Red squares", "Gray circles"), color = c("#a60f2dCC", "#3E3D3D90"), pch = c(15, 19), vertical_spacing = 2 ) # Note the text appears squished in this example since the width, height, # and resolution have been optimized to print the figure 6 in wide in the # report.
To vary color, symbol, and size of points by a grouping variable, call this function once for each value of the grouping variable. Add layers from bottom to top. The below example adds the red points last so they are plotted on top of the gray points.
add_texture_points( texture_df = NULL, color = "#a60f2dCC", pch = 19, size = 1.5, ... )add_texture_points( texture_df = NULL, color = "#a60f2dCC", pch = 19, size = 1.5, ... )
texture_df |
Data frame or matrix where each row is a soil sample and three numeric columns contain sand, silt, and clay percentages or proportions. The order of sand, silt, clay is required for correct plotting. |
color |
Color of the points. Defaults to WaSHI red. |
pch |
Numeric value of plotting symbol. See |
size |
Numeric expansion factor for points. Defaults to 1.5. |
... |
Other arguments passed to |
A list of x, y coordinates of the soil textures plotted.
Adapted from plotrix: https://github.com/plotrix/plotrix/blob/0d4c2b065e2c2d327358ac8cdc0b0d46b89bea7f/R/soil.texture.R
texture <- soils::washi_data |> dplyr::select( sand = sand_percent, silt = silt_percent, clay = clay_percent ) make_texture_triangle(body_font = "sans") # Add gray points add_texture_points( tail(texture, 5), color = "#3E3D3D90", pch = 19 ) # Add red points add_texture_points( head(texture, 5), color = "#a60f2dCC", pch = 15 ) # Note the text appears squished in this example since the width, height, # and resolution have been optimized to print the figure 6 in wide in the # report.texture <- soils::washi_data |> dplyr::select( sand = sand_percent, silt = silt_percent, clay = clay_percent ) make_texture_triangle(body_font = "sans") # Add gray points add_texture_points( tail(texture, 5), color = "#3E3D3D90", pch = 19 ) # Add red points add_texture_points( head(texture, 5), color = "#a60f2dCC", pch = 15 ) # Note the text appears squished in this example since the width, height, # and resolution have been optimized to print the figure 6 in wide in the # report.
Returns the most frequently occurring value in a character vector, ignoring missing values.
calculate_mode(x)calculate_mode(x)
x |
Character vector to calculate the mode from. |
A single value (character) that occurs most often in x.
calculate_mode(washi_data$crop)calculate_mode(washi_data$crop)
Validates soil particle-size fractions (sand, silt, and clay), completes missing values when possible, and assigns a USDA soil texture class.
classify_texture(df)classify_texture(df)
df |
A data frame containing the columns |
classify_texture() applies the following validation rules and
assumptions:
Eligibility
Each sample must contain values for at least two of
sand_percent, silt_percent, and clay_percent to be eligible for
fraction-based texture classification.
Errors (cause validation to fail)
All fraction values must fall within the range 0–100.
Samples with all three fractions must sum to 100 with a ±1 tolerance (allowable range 99–101).
Warnings (validation continues)
When exactly one fraction is missing, it is calculated as
100 - (sum of the other two).
Samples with fewer than two provided fractions and no provided
texture do not have sufficient data for texture classification.
These samples are retained and returned with an NA texture value.
Special cases (no warning or error)
Samples with fewer than two provided fractions and a provided texture will preserve the texture without modification.
A data frame with a texture column containing USDA soil texture
classes (if enough soil fraction data are provided). Soil fractions are
rounded to whole numbers.
Thresholds for texture classification are based on the USDA NRCS Soil Texture Calculator.
# Three samples classified without error df <- data.frame( sample_id = c(1, 2, 3), sand_percent = c(20, 45, 75), silt_percent = c(65, 35, 15), clay_percent = c(15, 20, 10) ) classify_texture(df) # Error when any fraction is outside the allowable range (0-100) df <- data.frame( sample_id = c(1, 2, 3), sand_percent = c(40, 0, 65), silt_percent = c(40, 55, 5), clay_percent = c(20, 110, 30) ) try(classify_texture(df)) # Error when fractions do not sum to 100 +/- 1 (allowable range: 99-101) df <- data.frame( sample_id = c(1, 2, 3), sand_percent = c(40, 0, 90), silt_percent = c(40, 55, 5), clay_percent = c(20, 45, 30) ) try(classify_texture(df)) # Warn when one fraction is missing # The missing fraction is calculated as 100 minus the other two df <- data.frame( sample_id = c(1, 2, 3), sand_percent = c(NA, 60, 25), silt_percent = c(45, 10, 40), clay_percent = c(50, 30, 35) ) classify_texture(df) # Warn when a sample has insufficient data and classification is skipped # One sample is missing two soil fractions df <- data.frame( sample_id = c(1, 2, 3), sand_percent = c(40, NA, 65), silt_percent = c(40, 55, 5), clay_percent = c(20, NA, 30) ) classify_texture(df) # No fractions provided, but texture is supplied # No warning; existing texture is preserved df <- data.frame( sample_id = c(1, 2), sand_percent = c(NA, NA), silt_percent = c(NA, NA), clay_percent = c(NA, NA), texture = c("Loam", "Sandy loam") ) classify_texture(df)# Three samples classified without error df <- data.frame( sample_id = c(1, 2, 3), sand_percent = c(20, 45, 75), silt_percent = c(65, 35, 15), clay_percent = c(15, 20, 10) ) classify_texture(df) # Error when any fraction is outside the allowable range (0-100) df <- data.frame( sample_id = c(1, 2, 3), sand_percent = c(40, 0, 65), silt_percent = c(40, 55, 5), clay_percent = c(20, 110, 30) ) try(classify_texture(df)) # Error when fractions do not sum to 100 +/- 1 (allowable range: 99-101) df <- data.frame( sample_id = c(1, 2, 3), sand_percent = c(40, 0, 90), silt_percent = c(40, 55, 5), clay_percent = c(20, 45, 30) ) try(classify_texture(df)) # Warn when one fraction is missing # The missing fraction is calculated as 100 minus the other two df <- data.frame( sample_id = c(1, 2, 3), sand_percent = c(NA, 60, 25), silt_percent = c(45, 10, 40), clay_percent = c(50, 30, 35) ) classify_texture(df) # Warn when a sample has insufficient data and classification is skipped # One sample is missing two soil fractions df <- data.frame( sample_id = c(1, 2, 3), sand_percent = c(40, NA, 65), silt_percent = c(40, 55, 5), clay_percent = c(20, NA, 30) ) classify_texture(df) # No fractions provided, but texture is supplied # No warning; existing texture is preserved df <- data.frame( sample_id = c(1, 2), sand_percent = c(NA, NA), silt_percent = c(NA, NA), clay_percent = c(NA, NA), texture = c("Loam", "Sandy loam") ) classify_texture(df)
ggplot2 plot to an interactive ggiraph
Convert a ggplot2 plot to an interactive ggiraph
convert_ggiraph(plot, ..., body_font = "Poppins", width = 6, height = 4)convert_ggiraph(plot, ..., body_font = "Poppins", width = 6, height = 4)
plot |
|
... |
Other arguments passed to |
body_font |
Font family to use throughout plot. Defaults to
|
width |
Width of SVG output in inches. Defaults to 6. |
height |
Height of SVG output in inches. Defaults to 4. |
Facetted strip plots with classes of girafe and htmlwidget.
# Read in wrangled example plot data df_plot_path <- soils_example("df_plot.RDS") df_plot <- readRDS(df_plot_path) # Make strip plot with all measurements and set scales based on # the category column and then apply theme. # Subset df to just biological measurement group df_plot_bio <- df_plot |> dplyr::filter(measurement_group == "Biological") # NOTE: the plot gets piped into the `set_scales()` function, which gets # added to `theme_facet_strip()`. plot <- make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales() + theme_facet_strip(body_font = "sans") # Convert static plot to interactive `ggiraph` convert_ggiraph(plot)# Read in wrangled example plot data df_plot_path <- soils_example("df_plot.RDS") df_plot <- readRDS(df_plot_path) # Make strip plot with all measurements and set scales based on # the category column and then apply theme. # Subset df to just biological measurement group df_plot_bio <- df_plot |> dplyr::filter(measurement_group == "Biological") # NOTE: the plot gets piped into the `set_scales()` function, which gets # added to `theme_facet_strip()`. plot <- make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales() + theme_facet_strip(body_font = "sans") # Convert static plot to interactive `ggiraph` convert_ggiraph(plot)
Intended for use during data ingestion and validation in the reporting workflow.
convert_to_numeric(data, measurement_cols)convert_to_numeric(data, measurement_cols)
data |
A data frame containing both metadata and quantitative measurement columns. |
measurement_cols |
A character vector of column names to convert to numeric. |
Non-numeric values in specified measurement columns, such as character values
commonly used to represent missing or censored measurements (e.g. "ND",
"<1", "-", or ""), are converted to NA. Warnings are emitted when
non-missing values are converted to NA, and when a column contains only NA
values after coercion, indicating it may be omitted from downstream summaries
or visualizations.
A data frame where specified measurement columns have been converted to numeric.
# Example data example_data <- data.frame( year = c(2023, 2023, 2024), sample_id = c("S1", "S2", "S3"), field_id = c("A", "A", "B"), ph = c("6.5", "ND", "7.1"), # partial NA (1 ND -> NA) nh4_n_mg_kg = c("12.3", "<1", ""), # partial NA (2 non-numeric -> NA) no3_n_mg_kg = c("NA", "NA", "NA"), # fully NA stringsAsFactors = FALSE ) # Specify the measurement columns measurement_cols = c("ph", "nh4_n_mg_kg", "no3_n_mg_kg") # Convert measurement columns to numeric clean_data <- convert_to_numeric(example_data, measurement_cols)# Example data example_data <- data.frame( year = c(2023, 2023, 2024), sample_id = c("S1", "S2", "S3"), field_id = c("A", "A", "B"), ph = c("6.5", "ND", "7.1"), # partial NA (1 ND -> NA) nh4_n_mg_kg = c("12.3", "<1", ""), # partial NA (2 non-numeric -> NA) no3_n_mg_kg = c("NA", "NA", "NA"), # fully NA stringsAsFactors = FALSE ) # Specify the measurement columns measurement_cols = c("ph", "nh4_n_mg_kg", "no3_n_mg_kg") # Convert measurement columns to numeric clean_data <- convert_to_numeric(example_data, measurement_cols)
Creates an RStudio project containing Quarto template and resources (images, style sheets, render.R script).
create_soils(path, template = "English", overwrite = FALSE, open = TRUE)create_soils(path, template = "English", overwrite = FALSE, open = TRUE)
path |
Name of project directory to be created. |
template |
Template type. Either "English" or "Spanish". |
overwrite |
Boolean. Overwrite the existing project? |
open |
Boolean. Open the newly created project? |
A new project directory containing template and resources.
Adapted from golem::create_golem().
## Not run: # Create temporary directory dir <- tempdir() # Create soils project create_soils(dir, overwrite = TRUE) # Delete temporary directory unlink(dir, recursive = TRUE) ## End(Not run)## Not run: # Create temporary directory dir <- tempdir() # Create soils project create_soils(dir, overwrite = TRUE) # Delete temporary directory unlink(dir, recursive = TRUE) ## End(Not run)
An example data dictionary for the Washington Soil Health Initiative (WaSHI) State of the Soils Assessment anonymized data.
data_dictionarydata_dictionary
data_dictionary A data frame with 32 rows and 7 columns.Name to group measurements by
Label of measurement group to be used as heading
Name of column in data set, used for joining
Order of how measurements are presented within each measurement_group
Abbreviated measurement name for labels
Measurement unit
HTML formatted abbreviation with unit for plots and tables
...
Color the background cells based on how the value compares to the project average. The project average must be the last row of the table. A footnote is added to the table describing what the dark and light colors mean.
format_ft_colors( ft, lighter_color = "#F2F0E6", darker_color = "#ccc29c", language = "English" )format_ft_colors( ft, lighter_color = "#F2F0E6", darker_color = "#ccc29c", language = "English" )
ft |
Flextable object |
lighter_color |
Lighter background color. Defaults to WaSHI cream. |
darker_color |
Darker background color. Defaults to WaSHI tan. |
language |
Language of the footnote. "English" (default) or "Spanish". |
# Read in wrangled example table data tables_path <- soils_example("tables.RDS") tables <- readRDS(tables_path) # Make the table ft <- flextable::flextable(tables$Biological) ft # Conditionally format background cell colors format_ft_colors(ft)# Read in wrangled example table data tables_path <- soils_example("tables.RDS") tables <- readRDS(tables_path) # Make the table ft <- flextable::flextable(tables$Biological) ft # Conditionally format background cell colors format_ft_colors(ft)
get_n_texture_by_var(results_long, producer_info, var)get_n_texture_by_var(results_long, producer_info, var)
results_long |
Data frame in tidy, long format containing |
producer_info |
Vector of producer values for the grouping variable. |
var |
Variable to group and summarize by. |
This function is deprecated. Its functionality has been incorporated directly
into summarize_by_var(). Do not use directly in new code.
Deprecated. Previously returned a data frame with n and Texture
by group.
summarize_by_var
Internal helper that uses the data dictionary to construct flextable column headers for a single measurement group.
get_table_headers(dictionary, group)get_table_headers(dictionary, group)
dictionary |
Data frame containing columns |
group |
Character |
Returns TRUE if there is at least one row in the data frame where all
specified columns are non-missing (no NA values).
has_complete_row(df, cols)has_complete_row(df, cols)
df |
A data frame. |
cols |
A character vector of column names to check. |
Logical scalar. TRUE if at least one row has all specified columns complete, FALSE otherwise.
has_complete_row(washi_data, c("crop", "county"))has_complete_row(washi_data, c("crop", "county"))
Returns TRUE if all values in a vector are missing (NA) or blank strings
("").
is_column_empty(column)is_column_empty(column)
column |
A vector to check. |
Logical scalar. TRUE if all values are NA or empty strings, FALSE
otherwise.
Make a flextable with column names from another dataframe
make_ft(table, header)make_ft(table, header)
table |
A dataframe with the contents of the desired flextable output. |
header |
Another dataframe with three columns:
|
Formatted flextable object.
# Read in wrangled table data headers_path <- soils_example("headers.RDS") headers <- readRDS(headers_path) tables_path <- soils_example("tables.RDS") tables <- readRDS(tables_path) # Input dataframes headers$Chemical tables$Chemical # Make the flextable make_ft( table = tables$Chemical, header = headers$Chemical ) |> # Style the flextable style_ft() |> # Add the white line under the columns with the same units unit_hline(header = headers$Chemical)# Read in wrangled table data headers_path <- soils_example("headers.RDS") headers <- readRDS(headers_path) tables_path <- soils_example("tables.RDS") tables <- readRDS(tables_path) # Input dataframes headers$Chemical tables$Chemical # Make the flextable make_ft( table = tables$Chemical, header = headers$Chemical ) |> # Style the flextable style_ft() |> # Add the white line under the columns with the same units unit_hline(header = headers$Chemical)
leaflet
Create an interactive web map with point locations and popups using
leaflet. This function is designed to work with data prepared using
prep_for_map().
make_interactive_map(df, primary_color = "#a60f2d")make_interactive_map(df, primary_color = "#a60f2d")
df |
Dataframe containing |
primary_color |
A character string specifying the color used for point features on the map (hex code or color name). Defaults to WaSHI red (#a60f2d). |
A leaflet map widget.
JavaScript code adapted from leaflet.extras.
make_static_map()
gis_df <- washi_data |> dplyr::distinct(latitude, longitude, .keep_all = TRUE) |> dplyr::select(c(latitude, longitude, farm_name, crop)) |> head(3) |> prep_for_map(label_heading = farm_name, label_body = crop) dplyr::glimpse(gis_df) make_interactive_map(gis_df)gis_df <- washi_data |> dplyr::distinct(latitude, longitude, .keep_all = TRUE) |> dplyr::select(c(latitude, longitude, farm_name, crop)) |> head(3) |> prep_for_map(label_heading = farm_name, label_body = crop) dplyr::glimpse(gis_df) make_interactive_map(gis_df)
ggplot2
Create a static map using basemap tiles and sample point locations. This
function is intended as a non-interactive alternative to
make_interactive_map().
make_static_map( df, label = field_id, provider = "Esri.WorldImagery", body_font = "sans", primary_color = "#a60f2d" )make_static_map( df, label = field_id, provider = "Esri.WorldImagery", body_font = "sans", primary_color = "#a60f2d" )
df |
Dataframe containing at minimum |
label |
Name of the column in |
provider |
Character string specifying the basemap tile provider, passed
to |
body_font |
Character string specifying the font family used for map labels. Defaults to "sans". |
primary_color |
A character string specifying the color used for point features on the map (hex code or color name). Defaults to WaSHI red (#a60f2d). |
A {ggplot2} object representing the static map.
gis_df <- washi_data |> dplyr::distinct(latitude, longitude, .keep_all = TRUE) |> dplyr::select(c(latitude, longitude, farm_name)) |> head(3) dplyr::glimpse(gis_df) ## Not run: static_map <- make_static_map(gis_df, label = farm_name) static_map ## End(Not run)gis_df <- washi_data |> dplyr::distinct(latitude, longitude, .keep_all = TRUE) |> dplyr::select(c(latitude, longitude, farm_name)) |> head(3) dplyr::glimpse(gis_df) ## Not run: static_map <- make_static_map(gis_df, label = farm_name) static_map ## End(Not run)
Make a facetted strip plot
make_strip_plot( df, ..., x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, language = "English" )make_strip_plot( df, ..., x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, language = "English" )
df |
Data frame to plot. |
... |
Other arguments passed to |
x |
Column for x-axis. For these strip plots, we recommend using a dummy
variable to act as a placeholder. Defaults to a column named |
y |
Column for y-axis. Defaults to |
id |
Column with unique identifiers for each sample to use as |
group |
Column to facet by. Defaults to |
tooltip |
Column with tooltip labels for interactive plots. |
language |
Language of the legend. |
Facetted ggplot2 strip plots.
# Read in wrangled example plot data df_plot_path <- soils_example("df_plot.RDS") df_plot <- readRDS(df_plot_path) # Subset df to just biological measurement group df_plot_bio <- df_plot |> dplyr::filter(measurement_group == "Biological") # Make strip plot with all measurements and set scales based on # the category column and then apply theme. # NOTE: the plot gets piped into the `set_scales()` function, which gets # added to `theme_facet_strip()`. make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales() + theme_facet_strip(body_font = "sans") # Example of strip plot without scales or theme functions make_strip_plot(df_plot_bio) # Example of strip plot with `x` set to the facet group instead of a dummy # variable. The dummy variable is what centers the points within the subplot. make_strip_plot( df_plot_bio, x = abbr_unit, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales() + theme_facet_strip(body_font = "sans")# Read in wrangled example plot data df_plot_path <- soils_example("df_plot.RDS") df_plot <- readRDS(df_plot_path) # Subset df to just biological measurement group df_plot_bio <- df_plot |> dplyr::filter(measurement_group == "Biological") # Make strip plot with all measurements and set scales based on # the category column and then apply theme. # NOTE: the plot gets piped into the `set_scales()` function, which gets # added to `theme_facet_strip()`. make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales() + theme_facet_strip(body_font = "sans") # Example of strip plot without scales or theme functions make_strip_plot(df_plot_bio) # Example of strip plot with `x` set to the facet group instead of a dummy # variable. The dummy variable is what centers the points within the subplot. make_strip_plot( df_plot_bio, x = abbr_unit, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales() + theme_facet_strip(body_font = "sans")
Make a texture triangle with USDA textural classes.
make_texture_triangle( body_font = "Poppins", show_names = TRUE, show_lines = TRUE, show_grid = FALSE )make_texture_triangle( body_font = "Poppins", show_names = TRUE, show_lines = TRUE, show_grid = FALSE )
body_font |
Font family to use throughout plot. Defaults to |
show_names |
Boolean. Defaults to |
show_lines |
Boolean. Defaults to |
show_grid |
Boolean. Defaults to |
Opens the graphics device with a triangle plot containing USDA textural classes.
Adapted from plotrix: https://github.com/plotrix/plotrix/blob/0d4c2b065e2c2d327358ac8cdc0b0d46b89bea7f/R/soil.texture.R
# Note the text appears squished in this example since the width, height, # and resolution have been optimized to print the figure 6 in wide in the # report. make_texture_triangle(body_font = "sans")# Note the text appears squished in this example since the width, height, # and resolution have been optimized to print the figure 6 in wide in the # report. make_texture_triangle(body_font = "sans")
Prepare a dataframe for use in interactive maps by creating formatted
label and popup columns from user-specified variables. This function is
intended for use prior to make_interactive_map().
prep_for_map(df, label_heading, label_body)prep_for_map(df, label_heading, label_body)
df |
A data frame containing at minimum |
label_heading |
A column in |
label_body |
A column in |
A data frame with additional label and popup columns,
suitable for input into make_interactive_map().
washi_data |> dplyr::distinct(latitude, longitude, .keep_all = TRUE) |> dplyr::select(c(latitude, longitude, farm_name, crop)) |> head(3) |> prep_for_map(label_heading = farm_name, label_body = crop) |> dplyr::glimpse()washi_data |> dplyr::distinct(latitude, longitude, .keep_all = TRUE) |> dplyr::select(c(latitude, longitude, farm_name, crop)) |> head(3) |> prep_for_map(label_heading = farm_name, label_body = crop) |> dplyr::glimpse()
Extract unique values from a single column of a data frame
pull_unique(df, target)pull_unique(df, target)
df |
A data frame containing the column of interest. |
target |
Column to extract unique values from (string or unquoted symbol). |
A vector of unique values from the specified column.
pull_unique(washi_data, "crop")pull_unique(washi_data, "crop")
Define styles for producer's samples versus all samples
set_scales( plot, primary_color = "#a60f2d", secondary_color = "#3E3D3D", other_color = "#ccc29c", language = "English" )set_scales( plot, primary_color = "#a60f2d", secondary_color = "#3E3D3D", other_color = "#ccc29c", language = "English" )
plot |
|
primary_color |
Color of producer's sample points. Defaults to WaSHI red |
secondary_color |
Color of sample points with |
other_color |
Color of sample points with |
language |
Language of the legend. |
ggplot object with manual alpha, color, shape, and size scales
applied.
# Read in wrangled example plot data df_plot_path <- soils_example("df_plot.RDS") df_plot <- readRDS(df_plot_path) # Subset df to just biological measurement group df_plot_bio <- df_plot |> dplyr::filter(measurement_group == "Biological") # Make strip plot make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales() + theme_facet_strip(body_font = "sans") # Example without setting scales make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label ) + theme_facet_strip(body_font = "sans")# Read in wrangled example plot data df_plot_path <- soils_example("df_plot.RDS") df_plot <- readRDS(df_plot_path) # Subset df to just biological measurement group df_plot_bio <- df_plot |> dplyr::filter(measurement_group == "Biological") # Make strip plot make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales() + theme_facet_strip(body_font = "sans") # Example without setting scales make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label ) + theme_facet_strip(body_font = "sans")
soils comes bundled with some example files in its inst/extdata
directory. This function make them easy to access.
soils_example(file = NULL)soils_example(file = NULL)
file |
Name of file. If |
Adapted from readxl::readxl_example().
soils_example() soils_example("df_plot.RDS")soils_example() soils_example("df_plot.RDS")
Style a flextable
style_ft( ft, header_font = "Lato", body_font = "Poppins", header_color = "#023B2C", header_text_color = "white", border_color = "#3E3D3D" )style_ft( ft, header_font = "Lato", body_font = "Poppins", header_color = "#023B2C", header_text_color = "white", border_color = "#3E3D3D" )
ft |
Flextable object. |
header_font |
Font of header text. Defaults to |
body_font |
Font of body text. Defaults to |
header_color |
Background color of header cells. Defaults to WaSHI green. |
header_text_color |
Color of header text. Defaults to white. |
border_color |
Color of border lines. Defaults to WaSHI gray. |
Styled flextable object.
# Read in wrangled example table data tables_path <- soils_example("tables.RDS") tables <- readRDS(tables_path) # Make the table ft <- flextable::flextable(tables$Biological) ft # Style the table style_ft(ft)# Read in wrangled example table data tables_path <- soils_example("tables.RDS") tables <- readRDS(tables_path) # Make the table ft <- flextable::flextable(tables$Biological) ft # Style the table style_ft(ft)
Summarize samples across the project
summarize_by_project(results_long)summarize_by_project(results_long)
results_long |
Dataframe in tidy, long format with columns: |
A data frame summarizing the average values across the project by
measurement_group and abbr. Includes a "Field or Average" column and,
if present, a Texture column.
Summarize producer's samples with averages by grouping variable
summarize_by_var(results_long, producer_samples, var)summarize_by_var(results_long, producer_samples, var)
results_long |
Dataframe in tidy, long format with columns: |
producer_samples |
Dataframe in tidy, long format with columns:
|
var |
Variable to summarize by, which should be present in both
|
A data frame with a "Field or Average" column summarizing the average
values by measurement group, abbr, and the specified grouping variable.
If a texture column is present, the data frame will contain a Texture
column containing the most frequent texture class per grouping variable.
Theme for facetted strip plots
theme_facet_strip( ..., body_font = "Poppins", strip_color = "#335c67", strip_text_color = "white" )theme_facet_strip( ..., body_font = "Poppins", strip_color = "#335c67", strip_text_color = "white" )
... |
Other arguments to pass into |
body_font |
Font family to use throughout plot. Defaults to |
strip_color |
Color of facet strip background. Defaults to WaSHI blue. |
strip_text_color |
Color of facet strip text. Defaults to white. |
# Read in wrangled example plot data df_plot_path <- soils_example("df_plot.RDS") df_plot <- readRDS(df_plot_path) # Subset df to just biological measurement group df_plot_bio <- df_plot |> dplyr::filter(measurement_group == "Biological") # Make strip plot with all measurements and set scales based on # the category column and then apply theme. # NOTE: the plot gets piped into the `set_scales()` function, which gets # added to `theme_facet_strip()`. make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales() + theme_facet_strip(body_font = "sans") # Example without setting theme make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales()# Read in wrangled example plot data df_plot_path <- soils_example("df_plot.RDS") df_plot <- readRDS(df_plot_path) # Subset df to just biological measurement group df_plot_bio <- df_plot |> dplyr::filter(measurement_group == "Biological") # Make strip plot with all measurements and set scales based on # the category column and then apply theme. # NOTE: the plot gets piped into the `set_scales()` function, which gets # added to `theme_facet_strip()`. make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales() + theme_facet_strip(body_font = "sans") # Example without setting theme make_strip_plot( df_plot_bio, x = dummy, y = value, id = sample_id, group = abbr_unit, tooltip = label, color = category, fill = category, size = category, alpha = category, shape = category ) |> set_scales()
Use when columns with the same units are merged together to add a bottom border to make it more obvious those columns share units.
unit_hline(ft, header)unit_hline(ft, header)
ft |
flextable object |
header |
Another dataframe with three columns:
|
Flextable object with bottom borders added.
# Read in wrangled table data headers_path <- soils_example("headers.RDS") headers <- readRDS(headers_path) tables_path <- soils_example("tables.RDS") tables <- readRDS(tables_path) # Input dataframes headers$Chemical tables$Chemical # Make the flextable make_ft( table = tables$Chemical, header = headers$Chemical ) |> # Style the flextable style_ft() |> # Add the white line under the columns with the same units unit_hline(header = headers$Chemical) # Example without `unit_hline()` make_ft( table = tables$Chemical, header = headers$Chemical ) |> # Style the flextable style_ft()# Read in wrangled table data headers_path <- soils_example("headers.RDS") headers <- readRDS(headers_path) tables_path <- soils_example("tables.RDS") tables <- readRDS(tables_path) # Input dataframes headers$Chemical tables$Chemical # Make the flextable make_ft( table = tables$Chemical, header = headers$Chemical ) |> # Style the flextable style_ft() |> # Add the white line under the columns with the same units unit_hline(header = headers$Chemical) # Example without `unit_hline()` make_ft( table = tables$Chemical, header = headers$Chemical ) |> # Style the flextable style_ft()
A subset of the Washington Soil Health Initiative (WaSHI) State of the Soils Assessment anonymized data. This data set presents each sample in its own row, with columns for each measurement.
washi_datawashi_data
washi_data A data frame with 100 rows and 41 columns:Year of sample
Anonymized IDs
Anonymized names
Truncated coordinates
Measured soil texture
Column name includes measurement and units; value is the measurement result
...