soilquality 2.3.0
Second piece of the SEM module, and like the first it needs no SEM.
New features
-
adjust_inherent()- removes the variation in each indicator attributable to properties a manager cannot change, so what remains is the part an index can fairly hold anyone responsible for. A soil should not be scored down for being what its geology made it. -
compute_sqi_df()gainsinherent, a one-sided formula. The adjustment runs before selection, scoring and weighting – correcting after any of those would undo it. Defaults toNULL: the pipeline never adjusts unless asked.
What it reports, which is half the value
$r_squared is the share of each indicator’s variation that was inheritance rather than management. On soil_inherent, Clay and pH come back above 0.9 – almost entirely inherited – while P and BD sit near 0.2, meaning they were mostly telling you about management all along. An indicator whose inherent model explains more than warn_r_squared (default 0.95) is flagged, because once nearly all the variation is inherited the residual is mostly noise.
Honest about what it is, and when not to use it
The arithmetic is lm() residuals, recentred on the indicator mean so the scale survives and the scoring functions behave exactly as before. A reviewer can fairly say “those are just residuals”. They are. What the function adds is an opinionated, documented, correctly-defaulted step in an index pipeline that no additive-index paper in the reviewed corpus performs, plus a report of what the adjustment cost.
Do not do it by reflex. Adjusting removes inherent variation by design. If your question is which of these soils is inherently better – siting, valuation, capability mapping – adjusting destroys the answer you came for. Adjust when the question is about management. The two look similar and are not.
A deliberate divergence from the plan
The specification proposed method = "none" as the default so that adjustment would always be a deliberate act. The default here is "residual", because calling the function is the deliberate act; a no-op default would mean adjust_inherent(data, indicators, ~ soil_type) silently did nothing, which is its own footgun. The deliberateness lives where it belongs instead: the inherent argument of compute_sqi_df() defaults to NULL. "none" remains available for switching the step off programmatically.
soilquality 2.2.0
New data
-
soil_inherent- 180 simulated samples carrying the columns an inherent-property adjustment needs and neither other dataset has: soil type, land-use history, a current management factor and a plot identifier. Five samples per plot, 36 plots, fully balanced.
This unblocks adjust_inherent(), which was blocked on data rather than on code: every column in soil_data and soil_structured is a measured property, so the function could not have been demonstrated, tested against an injected effect, or given a runnable example.
The property that makes it useful
The three factors are generated separately so that an adjustment can be shown to remove one kind of variation and preserve another:
| Factor | Inherent? | Drives |
|---|---|---|
soil_type |
yes |
Clay, CEC, pH
|
land_use_history |
yes | legacy OM, N
|
management |
no |
OM, P, BD
|
Residualising on the two inherent factors removes the soil-type effect and leaves the management effect standing. An adjustment that erased both would be useless. Here the management signal does not merely survive – it sharpens, because inherent variation was masking it:
| Indicator | soil_type p | management p |
|---|---|---|
OM |
0.83 → 1.00 | 2e-04 → 6e-23 |
CEC |
5e-56 → 1.00 | 0.09 → 8e-07 |
pH |
3e-91 → 1.00 | 0.48 → 5e-03 |
The R-squared of the inherent model separates the two kinds of indicator: Clay 0.95, pH 0.94, CEC 0.88 and OM 0.82 are mostly inherited, while P 0.22 and BD 0.19 are mostly managed.
It is nested, on purpose
Plot-level variance deliberately exceeds within-plot variance, giving intraclass correlations of 0.81 to 0.99. Maaz et al. (2023) found ICC above 0.75 for every indicator: samples within a plot are not independent, which invalidates ordinary standard errors, and most soil campaigns never check. Tests assert this rather than assuming it.
soilquality 2.1.0
First piece of the SEM module, and the one that needed no SEM at all.
New features
-
check_circularity()- refuses to let you regress a soil quality index on the indicators that built it. An index is a weighted sum of its components, so a model predicting it from those components must fit well: the R-squared is arithmetic, not evidence about soil. Sarapatka et al.- report R-squared = 0.99 from exactly this arrangement and name the cause themselves; Wang et al. (2025) conclude that carbon “affects” an index carbon helped build.
- Two modes, and the function distinguishes them. Explanation uses predictors from outside the index; overlap is an error. Decomposition – “which of my components dominates this index?” – is a fair question with a real answer, available via
allow_components = TRUE, and the result is labelled so that its fit statistic is not reported as a finding. -
Renaming is not laundering. Name matching alone would miss the commonest version: an index built on
OMregressed againstSOC, the same measurement times 1.724. Supplydataand every predictor is also checked by correlation against every component. Onsoil_structured,SOCis flagged as a proxy for bothOM(rho 0.99) andN(rho 0.96, through the C:N ratio) – reporting only the first would understate the entanglement. -
sqi_validate()gainsexternal_r_max(default 0.9) and now warns when the “external” criterion is really one of the index’s own indicators. That vector arrives unnamed, so the check is numerical. It is the same trap wearing a different hat, and the validation layer was exposed to it.
No new dependencies: this needs stats::cor() and set arithmetic.
soilquality 2.0.0
Breaking change
soil_ucayali has been removed. Use soil_data, which is a strict superset: the same 50 samples, the same SampleIDs, and all fifteen shared columns identical value for value, plus a sulfur (S) measurement that soil_ucayali lacked. The dataset carried no information of its own, and shipping both made the reference index look like there were two example datasets to choose between when there was one.
Migration is a rename:
# before
data(soil_ucayali)
compute_sqi_properties(soil_ucayali, properties = c("pH", "OM"))
# after
data(soil_data)
compute_sqi_properties(soil_data, properties = c("pH", "OM"))One caveat worth stating: code that auto-detects numeric columns rather than naming properties explicitly will now see sixteen columns instead of fifteen, because S is present. The selected minimum data set, and therefore the index, can change. Name your properties if that matters to you. The package’s own vignettes were updated on this basis and their results shift accordingly.
The major version is bumped because this removes an exported object.
Documentation
-
soil_datais retitled from “Extended Soil Data from Ucayali, Peru” — the “Extended” only meant “relative tosoil_ucayali” and no longer parses. Its help page now says plainly what it is good for and what it is not: it has almost no covariance structure (largest off-diagonal Spearman rho 0.66, one pair above 0.6), which is fine for scoring, weighting and aggregation, and useless for anything that reads the structure between indicators. Usesoil_structuredfor that. - The two remaining datasets are now described in the reference index by the job each does, rather than as interchangeable alternatives.
soilquality 1.7.0
Completes the upgrade begun in 1.1.0: adequacy testing, the main vignette, and the documentation the earlier phases deferred.
New features
-
pca_adequacy()- the two checks that a correlation matrix is worth factoring at all: the Kaiser-Meyer-Olkin measure of sampling adequacy, with Kaiser’s labels and a per-variable MSA, and Bartlett’s test of sphericity. Most published soil quality work skips both. -
pca_select_mds()gainsadequacy = c("report", "warn", "ignore"), reporting by default and warning on request when KMO falls below 0.6 or sphericity is not rejected. It reports rather than gates, because erroring would break every existing call.
A limitation worth knowing about
KMO requires inverting the correlation matrix, and soil data routinely makes that impossible: particle-size fractions sum to 100, so Sand, Silt and Clay together are exactly collinear, and organic matter and organic carbon are related by a fixed factor. When the matrix is singular, pca_adequacy() returns NA with an explanation naming the offending pairs, rather than erroring or quietly substituting a pseudo-inverse. Bartlett’s statistic is reported as NA for the same reason.
Bartlett’s test is also close to a formality on real data: with a decent sample size almost any set of soil properties rejects sphericity. Passing it is weak evidence; failing it is strong evidence, and that is what it is for.
Documentation
- New vignette,
vignette("building-and-validating-an-sqi"), walking the full pipeline: adequacy, selection by variance or centrality, functional grouping, the five scoring routes, weighting or not weighting, aggregation, and validation. - README gains the pipeline decision table and states why validation is the point rather than an optional extra.
-
Do not build an index from predicted properties. Documented on
compute_sqi_df()and in the README. Chaudhry et al. (2024): computing an SQI from spectrally predicted properties gave R² = 0.23, while predicting the index directly from the same spectra gave R² = 0.90, with individually acceptable property models.
soilquality 1.6.0
Adds reference-soil standardisation: scoring against an undisturbed soil rather than against the sample’s own extremes.
New features
-
standardize_to_reference()- scores an indicator relative to the same indicator in a non-degraded reference soil, which takes the value 1 while degraded samples fall toward 0. Three directions:"higher"givesx / reference;"lower"inverts toreference / x, because the undisturbed soil holds the minimum for bulk density and its like; and"optimum"uses the distance from the optimum, since a monotone scale would rank pH 8.0 above pH 6.5. -
reference_scoring()- the matchingscoring_ruleconstructor, so the route is reachable fromcompute_sqi_properties(). -
score_indicators()gains a"reference"type. -
sensitivity_resistance()- Kuzyakov’s second and much less used approach: each indicator’s relative change divided by the change in soil organic carbon. Below 1 the indicator degrades faster than carbon and is sensitive; above 1 it is resistant.
Why it matters, and what it costs
Every other scoring function normalises against the sample’s own extremes, which guarantees the best site scores about 1 by construction – whether it is pristine or merely the least ruined of a bad set. Two studies can both report 0.8 and mean entirely different soils.
The price is a defensible reference: same soil type, parent material and climate, undisturbed. Kuzyakov et al. call this the approach’s key disadvantage, and a fully converted landscape often has no such site left. A badly chosen reference does not add noise, it silently rescales every index built on it. The documentation says so rather than selling the method.
Two honest touches: a sample that beats the reference is capped at 1 with a warning naming how many did, because that usually means the reference is not the least disturbed soil available; and sensitivity_resistance() documents that Kuzyakov’s classification resolved cleanly on a Luvic Phaeozem and failed to separate on a Calcic Chernozem, so an untidy result is a fact about the soil rather than a failure of the analysis.
soilquality 1.5.0
Adds functional (EMDS) grouping: selecting one indicator per soil function rather than letting the whole pool compete on a single criterion.
New features
-
soil_function_groups- the five functions of Yuan and Shi (2026), after Li et al. (2023): carbon cycling, nutrient cycling, physical structure, buffering and filtration, and soil biodiversity. The biodiversity group ships empty on purpose – nothing in this package’s indicator vocabulary measures it, and a plausible-looking proxy would misrepresent which functions an index actually covers. -
assign_function_groups()- maps a set of property names onto those functions. Names that match nothing are reported in an"unassigned"element rather than silently dropped. -
pca_select_mds()andna_select_mds()gaingroups =, running selection independently inside each function. DefaultNULLkeeps pool-wide selection. In the network route a group too small for a graph (carbon cycling is two indicators) falls back to the most within-group correlated indicator, with a warning, recorded per group in$group_results. -
pca_select_mds()gainsselector = c("loading", "norm"). The norm value is Yuan eq. (2),N_i = sqrt(sum_k u_ik^2 * lambda_k)over components with eigenvalue >= 1, which judges an indicator across components instead of one at a time.
The relative loading rule, finally implemented
-
pca_select_mds()gainswithin =. The function has always taken the single highest-loading indicator per retained component; the rule stated in the literature keeps every indicator within 10% of that maximum, which generally yields a larger data set.within = NULL(the default) keeps the historical behaviour and the regression baseline;within = 0.10is the published rule.loading_thresholdis an absolute floor andwithina relative band – different mechanisms, combinable. - Documented that Yuan and Shi (2026) section 2.3.1 states this rule inverted, which would select the least informative variables. Their own section 2.3.2 states it correctly.
Why this matters, measured on soil_structured
Offered all fifteen indicators, ungrouped selection leaves entire functions with no representative:
| Route | Selected | Functions covered |
|---|---|---|
| network, ungrouped | OM, CEC | 2 of 4 |
| network, grouped | OM, P, N, Clay, EC | 4 of 4 |
| PCA, ungrouped | pH, Silt | 2 of 4 |
| PCA, grouped | SOC, P, Sand, EC | 4 of 4 |
The base-status indicators pH, Ca, Mg and EC are dropped wholesale by the ungrouped network route, because their module is peripheral to the graph.
Documentation
-
soil_function_groupsdocuments why grouping should be functional rather than by the familiar physical/chemical split: Maaz et al. (2023) tested that split by confirmatory factor analysis and found it has no statistical support.soil_property_sets$physicaland$chemicalare unchanged and remain useful for choosing what to measure – they are simply not a basis for selecting a minimum data set.
soilquality 1.4.0
New data
-
soil_structured- 120 simulated soil samples whose properties are related to one another the way real soil properties are. Generated from three latent gradients (texture, organic status, base status) so that the standard pedological relationships hold: compositional texture summing to 100,SOC = OM / 1.724(van Bemmelen),N = SOC / (C:N), CEC generated by clay and organic colloids, exchangeable bases tracking CEC and pH, bulk density falling with organic matter, conductivity carried by soluble bases. Forty indicator pairs reach|rho| >= 0.6, against one insoil_data. -
soil_dataandsoil_ucayaliare unchanged. They draw every property independently, which is fine for demonstrating scoring and aggregation but cannot exercise any method that reads the structure between indicators. Usesoil_structuredforna_select_mds(),mds_consensus()and, in future, functional grouping. - The dataset separates the two selection routes cleanly, which is worth seeing before choosing one: the network route selects the hubs (OM, CEC), the PCA route selects the high-variance and near-unique variables (pH, Silt), and their consensus is empty. That is the documented asymmetry made visible, not a defect in either method.
Bug fixes
-
na_select_mds()now runs the redundancy screen within each module rather than across the whole selected set. Screening globally discarded every module’s representative as redundant with the single most central indicator, collapsing the partition that the module step had just built – onsoil_structuredit returned one indicator where it should return two. - The disconnected-network warning no longer fires for a lone isolated indicator. A singleton component has no internal correlation to erase and is already reported in
$isolated; the warning is now raised only when more than one component contains actual structure.
soilquality 1.3.0
Adds correlation-network indicator selection, which chooses indicators by their centrality in a correlation network rather than by their contribution to variance.
New features
-
na_select_mds()- Minimum Data Set selection following Yuan and Shi (2026) section 2.3.2: a Spearman correlation network, Louvain communities, an eigenvector-centrality module filter, within-10% retention, weighted-degree tie-breaking, an optional redundancy screen, and centrality-derived weights. -
mds_consensus()- runs the PCA and network routes over the same data and returns the indicators both agree on. -
compute_sqi_df()gainsselect = "network"and anetwork_argslist, so the route reachescompute_sqi()andcompute_sqi_properties()too. The centrality weights are used unless a pairwise matrix is supplied. -
igraphis a suggested dependency, guarded byrequireNamespace(). This package is MIT-licensed and igraph is GPL-2+; a hard dependency in Imports would pull the combined work into GPL territory on distribution. Everything in this section degrades gracefully when igraph is absent.
Two defects in the published procedure, and what was done about them
-
Louvain is randomised, so the method is not deterministic. Six runs over identical input returned two different Minimum Data Sets during development.
na_select_mds()therefore takes aseed, defaulting to 1 and applied in a local scope that leaves the caller’s random stream untouched. Vary it to find out whether a selection is genuinely robust; stability at one seed is not evidence. -
On a disconnected network, eigenvector centrality goes to zero outside the dominant component – exactly zero under the reference BLAS, around 1e-17 under macOS Accelerate; the distinction is immaterial, since neither passes a usable threshold. A clique of three indicators correlating at 0.98 was discarded entire, and no
centrality_mincould rescue it. The newcomponent = "all"computes centrality within each connected component so each sub-network is judged on its own terms; the default reproduces the published behaviour, and a warning now states the consequence.
Note on the example data
soil_data is simulated from independent draws and carries almost no correlation structure: the largest off-diagonal Spearman rho is 0.66 and only one pair clears the default threshold. The network route collapses to a single indicator on it. That is a property of the fixture, not the method.
soilquality 1.2.0
Adds index validation – the ability to ask whether an index actually discriminates, rather than assuming it does.
New features
Validation
-
sqi_validate()- assesses a computed index on four diagnostics, in descending order of how much they should influence a judgement: the distribution across the five soil-health decision categories, the sensitivity index (max/min), fidelity to a total-data-set index, and correlation against an optional external criterion such as yield. - The distribution is the headline, and it warns. Maaz et al. (2023) found an additive index and an SEM index correlating at r = 0.96 while placing 94% vs 61% of plots in the middle bands: correlation is the wrong diagnostic for an index, the spread across decision categories is the right one. A warning fires above
middle_band_threshold(default 0.8) because a silent number gets ignored. -
sqi_stability()- runs the same samples through two or more recipes and reports whether the ranking survives: Spearman rho per pair, plus a flag when the best or worst sample changes. A high rank correlation does not rescue a changed extreme if the extreme is what you act on. -
plot_sqi_validation()- the distribution plot, accepting ansqi_validation, ansqi_resultor a bare numeric vector. -
compute_sqi_df()gainsselect = c("pca", "none"). With"none"the selection step is skipped and every numeric indicator is used, which is how the total-data-set index thatsqi_validate()measures fidelity against is built. PCA is still run and reported either way.
Note on the example data
Running sqi_validate() on the package’s own default recipe applied to soil_data fires the middle-band warning: the resulting SQI spans roughly 0.36-0.70, so 100% of samples land in the middle bands and the “very low” and “very high” categories are empty. This is not a bug – it is the diagnostic working, on exactly the pathology it was built to expose.
soilquality 1.1.0
Broadens the package from a single SQI route (PCA-MDS, AHP/loading weights, linear scoring, weighted additive aggregation) toward the routes the soil quality literature actually uses. This release covers non-linear scoring and weight-free aggregation. All additions are opt-in; the default pipeline produces exactly the values it produced in 1.0.0, and a golden-output regression test now enforces that.
New features
Non-linear (sigmoidal) scoring
-
score_sigmoid()- scores an indicator withS = 1 / (1 + (x/x0)^b), the dominant scoring form in the SQI literature. Bothx0(the value scoring 0.5) andb(steepness) are parameters. Theb = 2.5default is a convention inherited from the literature with empirical support for pH/TN/SOC/P only, not a general constant, and the documentation says so. -
sigmoid_scoring()- the matchingscoring_ruleconstructor, so the new curve is reachable fromcompute_sqi_properties(). -
score_indicators()gains a"sigmoid"scoring type alongside the existinghigher/lower/optimum/threshold. -
standard_scoring_rules()gainsscoring = c("linear", "sigmoid")andb. pH deliberately remains an optimum-range rule under"sigmoid": the sigmoidal curve is monotonic and has no optimum form.
Area-based (weight-free) aggregation
-
sqi_area()- aggregates scored indicators as the area of the radar diagram they trace,A = 0.5 * sum(s^2) * sin(2*pi/n)(Kuzyakov et al. 2020, eq. 2). This ignores weights entirely, sidestepping the most contested step in the pipeline. Supplyingreferencereports the result as a ratio against a non-degraded reference soil, which is what makes area-based values comparable across studies – the absolute value is not. -
compute_sqi_df()gainsmethod = c("weighted", "area")andreference. Both flow throughcompute_sqi()andcompute_sqi_properties()via.... The returnedsqi_resultnow carries amethodelement.
Documentation
-
score_sigmoid()documents that the literature contradicts itself on linear vs non-linear scoring (Yuan 2026 finds non-linear better; Bilgili et al. 2017, cited in Yuan’s own introduction, finds the opposite) and recommends computing both. -
sqi_area()documents why the formula squares each score rather than multiplying adjacent radii: the square form is order-independent, whereas the true polygon area would depend on the arbitrary order of indicators around the diagram.
Internal
- Added a golden-output regression baseline pinning the MDS, PCA variance decomposition, weights and SQI values of the default pipeline against the shipped
soil_data. Every change from here must leave it green or declare itself a break. - Migrated the test suite to
testthatedition 3 (Config/testthat/edition: 3). No test changes were required. User-facing behaviour is unaffected.
soilquality 1.0.0
Release Date: 2025-12-07
Initial Release
This is the first public release of the soilquality package, providing comprehensive tools for calculating Soil Quality Index (SQI) using scientifically validated methods combining Principal Component Analysis (PCA) and Analytic Hierarchy Process (AHP).
Major Features
Core Functionality
- PCA-based MDS Selection: Automated selection of Minimum Data Set indicators using Principal Component Analysis with configurable variance and loading thresholds
- AHP Weighting System: Expert-based indicator weighting with consistency ratio validation following Saaty’s methodology
- Flexible Scoring Framework: Multiple normalization methods to handle different soil property characteristics
- Property Selection: Pre-defined property sets (basic, standard, comprehensive, physical, chemical, fertility) and custom property selection
- Standard Scoring Rules: Automatic rule assignment based on property name patterns for common soil properties
- Comprehensive Visualization: Five plot types (distribution, indicators, weights, scree, biplot) plus multi-panel reports
- Interactive Application: Shiny-based GUI for non-programmers with file upload, configuration, and results download
Workflow Options
-
File-based workflow:
compute_sqi()for CSV input/output -
In-memory workflow:
compute_sqi_df()for data frame processing -
Enhanced workflow:
compute_sqi_properties()with property selection and constructor-based scoring
Complete Function Reference
Data Handling Functions
-
read_soil_csv()- Import soil data from CSV files with encoding handling -
standardize_numeric()- Z-score standardization of numeric columns -
to_numeric()- Safe type conversion with NA for failures
PCA and MDS Selection
-
pca_select_mds()- Perform PCA and select minimum data set based on variance and loading thresholds
AHP Weighting Functions
-
ahp_weights()- Calculate indicator weights from pairwise comparison matrix using eigenvalue decomposition -
create_ahp_matrix()- Interactive or programmatic AHP matrix creation with validation -
ratio_to_saaty()- Convert importance ratios to Saaty scale (1-9) -
print.ahp_matrix()- S3 print method for AHP matrix objects
Scoring Functions (Low-level)
-
score_higher_better()- Normalize properties where higher values indicate better quality -
score_lower_better()- Normalize properties where lower values indicate better quality -
score_optimum()- Normalize properties with optimal range using linear or quadratic penalty -
score_threshold()- Custom piecewise linear scoring based on threshold-score pairs -
score_indicators()- Apply scoring functions to multiple indicators
Scoring Constructors (User-facing)
-
higher_better()- Constructor for higher-is-better scoring rules -
lower_better()- Constructor for lower-is-better scoring rules -
optimum_range()- Constructor for optimal range scoring with tolerance -
threshold_scoring()- Constructor for custom threshold-based scoring -
print.scoring_rule()- S3 print method for scoring rule objects
Property Sets and Standard Rules
-
soil_property_sets- Pre-defined collections: basic (pH, OM, P, K), standard (9 properties), comprehensive (14 properties), physical, chemical, fertility -
standard_scoring_rules()- Automatic scoring rule assignment based on property name patterns
SQI Computation Functions
-
compute_sqi()- File-based SQI computation with CSV input/output -
compute_sqi_df()- In-memory SQI computation with data frame input -
compute_sqi_properties()- Enhanced SQI computation with property selection and constructor-based scoring
Visualization Functions
-
plot.sqi_result()- S3 plot method supporting five plot types:- “distribution”: Histogram of SQI values with mean line
- “indicators”: Boxplots of indicator scores
- “weights”: Bar chart of AHP weights with CR annotation
- “scree”: Variance explained by principal components
- “biplot”: PCA biplot of observations and variables
-
plot_sqi_report()- Generate comprehensive 2x2 multi-panel visualization report
Interactive Tools
-
run_sqi_app()- Launch interactive Shiny application with file upload, property selection, scoring configuration, AHP input, results display, and CSV download
Example Datasets
-
soil_ucayali- Real soil property data from Ucayali, Peru (50 samples, 14 properties)- Physical properties: Sand, Silt, Clay, BD (bulk density)
- Chemical properties: pH, OM (organic matter), SOC (soil organic carbon)
- Nutrients: N, P, K, CEC, Ca, Mg
- Other: EC (electrical conductivity)
Documentation
Vignettes
- Introduction to soilquality: Basic workflow, installation, quick start examples, result interpretation
- Advanced Usage: Property selection strategies, custom scoring rules, AHP matrix creation, visualization options
- AHP Matrices Guide: AHP methodology explanation, creating pairwise comparisons, consistency ratio interpretation, tips for improving inconsistent matrices
Testing and Quality
Dependencies
Required (Imports)
-
stats- PCA (prcomp), eigenvalue calculations -
utils- CSV reading, data manipulation
Known Limitations
Technical Constraints
- PCA requires at least 3 numeric variables for meaningful dimensionality reduction
- Sufficient observations recommended (n >= p) for stable PCA results
- AHP consistency ratio should be < 0.1 for reliable weights (warning issued if exceeded)
- Interactive AHP matrix creation requires interactive R session (not available in batch mode)
Scope Limitations
- Package focuses on PCA-based MDS selection; other selection methods not included
- AHP is the only weighting method implemented; other MCDA methods not included
- Visualization uses base R graphics only (no ggplot2 integration)
- Shiny app requires manual launch; no deployed web version included
Future Development
Potential enhancements for future versions: - Additional MDS selection methods (correlation-based, expert selection) - Alternative weighting methods (equal weights, data-driven weights) - ggplot2-based visualization option - Additional scoring functions (membership functions, fuzzy logic) - Spatial analysis integration - Time series support for monitoring - Export to additional formats (PDF reports, GIS layers)
Acknowledgments
This package implements methodologies from soil quality assessment literature: - Andrews et al. (2004) - Soil Management Assessment Framework - Saaty (1980) - Analytic Hierarchy Process - PCA-based MDS selection approaches widely used in soil science research
Citation
To cite this package in publications:
Carbajal, Carlos (2025). soilquality: Soil Quality Index Calculation with PCA and AHP. R package version 1.0.0. https://github.com/ccarbajal16/soilquality
Getting Help
- Function documentation:
?function_nameorhelp(function_name) - Vignettes:
browseVignettes("soilquality") - Issues: https://github.com/ccarbajal16/soilquality/issues
