diff --git a/CRAN-SUBMISSION b/CRAN-SUBMISSION deleted file mode 100644 index e805da4..0000000 --- a/CRAN-SUBMISSION +++ /dev/null @@ -1,3 +0,0 @@ -Version: 1.0.1 -Date: 2024-07-27 16:14:14 UTC -SHA: a9383a8960cbca2dfd399ee24cd8ddb53516dd06 diff --git a/DESCRIPTION b/DESCRIPTION index 780d07c..59322b1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: paar Type: Package Title: Precision Agriculture Data Analysis -Version: 1.0.1 +Version: 1.0.2.9000 Authors@R: c( person("Pablo", "Paccioretti", email = "pablopaccioretti@agro.unc.edu.ar", diff --git a/NEWS.md b/NEWS.md index 8e36e2b..f7963df 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,6 @@ -# (development version) +# paar (development version) + +# paar 1.0.2 * Help pages were revised for clarity, consistency, and improved user guidance [#21](https://github.com/PPaccioretti/paar/issues/21) * Now Summary index is calculated correctly. diff --git a/README.Rmd b/README.Rmd index 3b9426b..96462d0 100644 --- a/README.Rmd +++ b/README.Rmd @@ -22,8 +22,7 @@ knitr::opts_chunk$set( [![R-CMD-check](https://github.com/PPaccioretti/paar/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/PPaccioretti/paar/actions/workflows/R-CMD-check.yaml) -The goal of `paar` is to provide useful functions for -precision agriculture spatial data depuration. +The goal of `paar` is to provide useful tools for cleaning and processing spatial data in precision agriculture. ## Installation @@ -41,8 +40,8 @@ pak::pkg_install("PPaccioretti/paar") ## Example -The package has a complete protocol for automating error removal. Default -values of all functions are optimized for precision agricultural data. +The package provides a complete protocol for automated error removal. +Default values of all functions are optimized for precision agriculture data. ```{r example, message=FALSE} library(paar) @@ -50,30 +49,27 @@ library(sf) data("barley", package = 'paar') ``` -`barley` data contains barley grain yield which were obtained using calibrated commercial yield monitors, mounted on combines equipped with DGPS. +The `barley` dataset contains grain yield data collected were using calibrated commercial yield monitors, mounted on combines equipped with DGPS. ```{r barley} #Convert barley data to an spatial object -barley_sf <- st_as_sf(barley, - coords = c("X", "Y"), - crs = 32720) +barley_sf <- st_as_sf(barley, coords = c("X", "Y"), crs = 32720) barley_dep <- - depurate(barley_sf, - "Yield") + depurate(barley_sf, "Yield") # Summary of depurated data summary(barley_dep) ``` -Spatial yield values before and after depuration process can be plotted +Spatial yield values before and after the depuration process can be visualized ```{r, fig.height=2, fig.height=5, out.width="50%", fig.show="hold"} plot(barley_sf["Yield"], main = "Before depuration") plot(barley_dep$depurated_data["Yield"], main = "After depuration") ``` -Also distribution of yield values can be plotted +The distribution of yield values can also be compared ```{r, fig.height=2, fig.height=5, out.width="50%", fig.show="hold"} boxplot(barley_sf[["Yield"]], main = "Before depuration") diff --git a/README.md b/README.md index 401cb23..438d26c 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](h [![R-CMD-check](https://github.com/PPaccioretti/paar/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/PPaccioretti/paar/actions/workflows/R-CMD-check.yaml) -The goal of `paar` is to provide useful functions for precision -agriculture spatial data depuration. +The goal of `paar` is to provide useful tools for cleaning and +processing spatial data in precision agriculture. ## Installation @@ -33,29 +33,27 @@ pak::pkg_install("PPaccioretti/paar") ## Example -The package has a complete protocol for automating error removal. -Default values of all functions are optimized for precision agricultural +The package provides a complete protocol for automated error removal. +Default values of all functions are optimized for precision agriculture data. ``` r library(paar) library(sf) +#> Warning: package 'sf' was built under R version 4.5.2 data("barley", package = 'paar') ``` -`barley` data contains barley grain yield which were obtained using +The `barley` dataset contains grain yield data collected were using calibrated commercial yield monitors, mounted on combines equipped with DGPS. ``` r #Convert barley data to an spatial object -barley_sf <- st_as_sf(barley, - coords = c("X", "Y"), - crs = 32720) +barley_sf <- st_as_sf(barley, coords = c("X", "Y"), crs = 32720) barley_dep <- - depurate(barley_sf, - "Yield") + depurate(barley_sf, "Yield") #> Concave hull algorithm is computed with #> concavity = 2 and length_threshold = 0 @@ -67,23 +65,24 @@ summary(barley_dep) #> 99 (1.3%) 6 (0.081%) ``` -Spatial yield values before and after depuration process can be plotted +Spatial yield values before and after the depuration process can be +visualized ``` r plot(barley_sf["Yield"], main = "Before depuration") plot(barley_dep$depurated_data["Yield"], main = "After depuration") ``` - + -Also distribution of yield values can be plotted +The distribution of yield values can also be compared ``` r boxplot(barley_sf[["Yield"]], main = "Before depuration") boxplot(barley_dep$depurated_data[["Yield"]], main = "After depuration") ``` - + ## References diff --git a/cran-comments.md b/cran-comments.md index 6c4cb92..6f33fc9 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,7 +1,13 @@ -## R CMD check results +## Test environments +* macOS (devel and release) +* windows (devel and release) +* Ubuntu (devel and release) + +## Submission note -0 errors | 0 warnings | 1 note +* This submission fixes some bugs +* No reverse dependencies -* This is a new release. +## R CMD check results -We are resubmitting the package after addressing the CRAN comments from the first submission. +0 errors | 0 warnings | 0 note \ No newline at end of file diff --git a/man/compare_zone.Rd b/man/compare_zone.Rd index bddfe0d..9fe3a83 100644 --- a/man/compare_zone.Rd +++ b/man/compare_zone.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/compare_zone.R \name{compare_zone} \alias{compare_zone} -\title{Compare spatial zone means} +\title{Compare means between spatial zones} \usage{ compare_zone( data, @@ -15,25 +15,58 @@ compare_zone( ) } \arguments{ -\item{data}{\code{sf} object with zones} +\item{data}{an \code{sf} object containing the spatial zones} -\item{variable}{\code{character} or \code{sf} object to use for mean comparison} +\item{variable}{either: +\itemize{ + \item a \code{character} vector with column names in \code{data}, or + \item an \code{sf} object with external variables to be compared. In this + case, values are spatially joined to \code{data}. +}} -\item{zonesCol}{\code{character} colname from data were zone are specified} +\item{zonesCol}{\code{character}. Column name in \code{data} defining zones} -\item{alpha}{\code{numeric} Significance level to use for comparison} +\item{alpha}{\code{numeric}. Significance level for mean comparison} -\item{join}{function to use for st_join if variable is \code{sf} object} +\item{join}{function used in \code{sf::st_join} when \code{variable} is an +external \code{sf} object (default: \code{sf::st_nearest_feature})} -\item{returnLSD}{\code{logical} when LSD calculates with spatial variance should be returned} +\item{returnLSD}{\code{logical}. If \code{TRUE}, returns the LSD value used +for comparisons} -\item{grid_dim}{\code{numeric} grid dimentins to estimate spatial variance} +\item{grid_dim}{\code{numeric}. Grid resolution used to estimate spatial +variance when interpolating external variables. If missing, it is +automatically determined.} } \value{ -\code{list} with differences and descriptive_stat +A list with: +\describe{ + \item{differences}{list of data frames with mean comparisons per variable} + \item{descriptive_stat}{data frame with descriptive statistics and spatial variance} +} } \description{ -Compare spatial zone means +Compares variable means across spatial zones using a spatially-adjusted +least significant difference (LSD) approach based on kriging variance. + +The function accounts for spatial variability by estimating semivariograms +and deriving a spatial variance component, which is then used to assess +differences between zone means. +} +\details{ +When \code{variable} is an external \code{sf} object, values are interpolated +using ordinary kriging before comparison. Otherwise, cross-validation of the +variogram model is used to estimate spatial variance. + +Pairwise comparisons between zones are evaluated using a spatially-adjusted +LSD criterion: + +\deqn{LSD = z_{1-\alpha/2} \times \sigma_{spatial}} + +where \eqn{\sigma_{spatial}} is derived from kriging variance. + +Results are presented using compact letter displays to indicate groups +of zones that are not significantly different. } \examples{ library(sf) @@ -55,6 +88,6 @@ compare_zone(data_clusters, "Elev", "Cluster_3") \references{ Paccioretti, P., Córdoba, M., & Balzarini, M. (2020). FastMapping: Software to create field maps and identify management zones -in precision agriculture. Computers and Electronics in Agriculture, 175, -105556 https://doi.org/10.1016/j.compag.2020.105556. +in precision agriculture. \emph{Computers and Electronics in Agriculture}, +175, 105556. \doi{10.1016/j.compag.2020.105556} } diff --git a/man/depurate.Rd b/man/depurate.Rd index 230d7da..1ca7c2d 100644 --- a/man/depurate.Rd +++ b/man/depurate.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/depurate.R \name{depurate} \alias{depurate} -\title{Remove errors from spatial data} +\title{Spatial data depuration (error removal)} \usage{ depurate( x, @@ -21,69 +21,98 @@ depurate( ) } \arguments{ -\item{x}{an \code{sf} points object} +\item{x}{An \code{sf} object with POINT geometries.} -\item{y}{\code{character} with the name of the variable to use for -depuration/filtering process} +\item{y}{A \code{character} string indicating the variable name used +for filtering. If missing and only one attribute column is present, +it is used by default.} -\item{toremove}{\code{character} vector specifying the procedure to -implement for errors removal. Default 'edges', 'outlier', 'inlier'. -See Details.} +\item{toremove}{A \code{character} vector specifying which procedures +to apply. Options are \code{"edges"}, \code{"outlier"}, and +\code{"inlier"}. The order of execution is fixed and cannot be modified.} -\item{crs}{coordinate reference system: integer with the EPSG code, -or character with proj4string to convert coordinates if \code{x} has -longitude/latitude data} +\item{crs}{Coordinate reference system used when transforming +longitude/latitude data. Can be an EPSG code or proj4string.} -\item{buffer}{\code{numeric} distance in meters to be removed. Negative -values are recommended} +\item{buffer}{A \code{numeric} value indicating the distance (in meters) +for edge removal. Negative values are recommended to shrink boundaries.} -\item{ylimitmax}{\code{numeric} of length 1 indicating the maximum limit -for the \code{y} variable. If \code{NA} \code{Inf} is assumed} +\item{ylimitmax}{Numeric upper bound for \code{y}. If \code{NA}, \code{Inf} +is used.} -\item{ylimitmin}{\code{numeric} of length 1 indicating the minimum limit -for the \code{y} variable. If \code{NA} \code{-Inf} is assumed} +\item{ylimitmin}{Numeric lower bound for \code{y}. If \code{NA}, \code{-Inf} +is used.} -\item{sdout}{\code{numeric} values outside the interval -\eqn{mean ± sdout × sdout} values will be removed} +\item{sdout}{Numeric multiplier for standard deviation used to detect +global outliers.} -\item{ldist}{\code{numeric} lower distance bound to identify neighbors} +\item{ldist}{Numeric lower distance bound for neighborhood definition.} -\item{udist}{\code{numeric} upper distance bound to identify neighbors} +\item{udist}{Numeric upper distance bound for neighborhood definition.} -\item{criteria}{\code{character} with "LM" and/or "MP" for methods to -identify spatial outliers} +\item{criteria}{Character vector specifying spatial outlier detection +methods: \code{"LM"} (Local Moran) and/or \code{"MP"} (Moran Plot).} -\item{zero.policy}{default NULL, use global option value; -if FALSE stop with error for any empty neighbors sets, -if TRUE permit the weights list to be formed with zero-length -weights vectors} +\item{zero.policy}{Logical. If \code{TRUE}, allows empty neighbor sets; +if \code{FALSE}, stops with an error.} -\item{poly_border}{\code{sf} object with one polygon or NULL. Can be -the result of \code{concaveman::concaveman}} +\item{poly_border}{Optional \code{sf} polygon defining field boundaries. +If \code{NULL}, a hull is computed automatically.} } \value{ -an object of class \code{paar} with two elements: +An object of class \code{paar} (list) with: \describe{ - \item{depurated_data}{\code{sf} object with the data after the removal - process} - \item{condition}{\code{character} vector with the condition of each - observation} - } + \item{depurated_data}{Filtered \code{sf} object} + \item{condition}{Character vector indicating the reason each observation + was removed (or \code{NA} if retained)} +} } \description{ -Data can be filtered by null, edge values, global - outliers and spatial outliers or local defective observations. Default - values are optimized for precision agricultural data. +Filters spatial point data by removing erroneous observations based on +geometric, statistical, and spatial criteria. The function implements a +sequential depuration workflow commonly used in precision agriculture. } \details{ -Possible values for \code{toremove} are one or more elements of: +The depuration process is applied in a fixed sequence: + +\enumerate{ + \item Edge removal (\code{"edges"}) + \item Global outlier removal (\code{"outlier"}) + \item Spatial outlier removal (\code{"inlier"}) +} + +The \code{toremove} argument controls which of these steps are applied, +but **does not modify the order of execution**. + +Available procedures are: + \describe{ - \item{edges}{All data points for a distance of \code{buffer} m from data - edges are deleted.} - \item{outlier}{Values that are outside the mean±\code{sdout} are removed} - \item{inlier}{Local Moran index of spatial autocorrelation is calculated - for each datum as a tool to identify inliers} + \item{edges}{ + Removes points located within a specified \code{buffer} distance from + the field boundary. The boundary is computed using a concave hull + (\code{concaveman}) or a convex hull if the package is not available. + } + + \item{outlier}{ + Removes global outliers based on: + \itemize{ + \item user-defined limits (\code{ylimitmin}, \code{ylimitmax}) + \item statistical thresholds defined as + \eqn{mean \pm sdout \times sd} + } + } + + \item{inlier}{ + Identifies and removes spatial outliers using: + \itemize{ + \item Local Moran's I statistic ("LM") + \item Moran scatterplot influence ("MP") + } + } } + +Default parameter values are tuned for precision agriculture datasets +(e.g., yield maps). } \examples{ library(sf) @@ -103,7 +132,8 @@ depurated_data <- depurated$depurated_data all_data_condition <- cbind(depurated, barley) } \references{ -Vega, A., Córdoba, M., Castro-Franco, M. et al. Protocol for -automating error removal from yield maps. Precision Agric 20, 1030–1044 -(2019). https://doi.org/10.1007/s11119-018-09632-8 +Vega, A., Córdoba, M., Castro-Franco, M. et al. (2019). +Protocol for automating error removal from yield maps. +\emph{Precision Agriculture}, 20, 1030–1044. +\doi{10.1007/s11119-018-09632-8} } diff --git a/man/figures/README-unnamed-chunk-2-1.png b/man/figures/README-unnamed-chunk-2-1.png index da5b932..f68b4dd 100644 Binary files a/man/figures/README-unnamed-chunk-2-1.png and b/man/figures/README-unnamed-chunk-2-1.png differ diff --git a/man/figures/README-unnamed-chunk-2-2.png b/man/figures/README-unnamed-chunk-2-2.png index 2130bfb..c53b8a2 100644 Binary files a/man/figures/README-unnamed-chunk-2-2.png and b/man/figures/README-unnamed-chunk-2-2.png differ diff --git a/man/figures/README-unnamed-chunk-3-1.png b/man/figures/README-unnamed-chunk-3-1.png index 9d730d3..1b2cfc8 100644 Binary files a/man/figures/README-unnamed-chunk-3-1.png and b/man/figures/README-unnamed-chunk-3-1.png differ diff --git a/man/figures/README-unnamed-chunk-3-2.png b/man/figures/README-unnamed-chunk-3-2.png index d9672bb..a63391e 100644 Binary files a/man/figures/README-unnamed-chunk-3-2.png and b/man/figures/README-unnamed-chunk-3-2.png differ diff --git a/man/fuzzy_k_means.Rd b/man/fuzzy_k_means.Rd index 0c7f9a3..a5568ed 100644 --- a/man/fuzzy_k_means.Rd +++ b/man/fuzzy_k_means.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/fuzzy_k_means.R \name{fuzzy_k_means} \alias{fuzzy_k_means} -\title{Fuzzy k-means clustering} +\title{Fuzzy k-means clustering (non-spatial)} \usage{ fuzzy_k_means( data, @@ -13,28 +13,51 @@ fuzzy_k_means( ) } \arguments{ -\item{data}{sf object} +\item{data}{an \code{sf} object with point geometries} -\item{variables}{variables to use for clustering, if missing, all numeric -variables will be used} +\item{variables}{\code{character} vector with variable names used for clustering. +If missing, all numeric variables in \code{data} are used.} -\item{number_cluster}{\code{numeric} vector with number of final clusters} +\item{number_cluster}{\code{numeric} vector indicating the number of clusters +to evaluate (e.g., \code{3:5})} -\item{fuzzyness}{A number greater than 1 giving the degree of fuzzification.} +\item{fuzzyness}{\code{numeric} value greater than 1 controlling the degree of +fuzziness in clustering (see \code{e1071::cmeans})} -\item{distance}{\code{character} Must be one of the following: -If "euclidean", the mean square error, if "manhattan", the mean -absolute error is computed. Abbreviations are also accepted.} +\item{distance}{\code{character} distance metric for clustering. +One of \code{"euclidean"} or \code{"manhattan"} (abbreviations allowed)} } \value{ -a list with classification results and indices to select best number of -clusters. +A list with: +\describe{ + \item{cluster}{\code{data.frame} with cluster assignments for each + evaluated number of clusters} + \item{indices}{\code{data.frame} with clustering validity indices} + \item{summaryResults}{\code{data.frame} with clustering metrics} +} } \description{ -Performs a vectorized fuzzy k-means clustering, this procedure -it is not spatial. The function is almost a wrapper of the function cmeans -from the package e1071. Is intended to be used when `KM-sPC` procedure is not -possible because data set has only 1 variable. +Performs fuzzy k-means clustering on tabular data (non-spatial). +This function is a lightweight wrapper around \code{e1071::cmeans}, +providing a vectorized workflow and clustering quality indices. + +It is primarily intended as a fallback method when spatial clustering +(e.g., \code{kmspc}) cannot be applied, such as when only one variable +is available. +} +\details{ +Missing values are removed prior to clustering. Observations with missing +values are reintroduced in the output with \code{NA} cluster assignments. + +Clustering is performed for each value in \code{number_cluster}, and +several indices are returned to assist in selecting the optimal number +of clusters: +\itemize{ + \item Xie-Beni index + \item Partition coefficient + \item Partition entropy + \item Summary index +} } \examples{ library(sf) @@ -65,3 +88,6 @@ wheat_clustered <- cbind(wheat_sf, fuzzy_k_means_results$cluster) # Plot the results plot(wheat_clustered[, "Cluster_2"]) } +\seealso{ +\code{\link{kmspc}} +} diff --git a/man/kmspc.Rd b/man/kmspc.Rd index c686615..81ef64d 100644 --- a/man/kmspc.Rd +++ b/man/kmspc.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/kmspc.R \name{kmspc} \alias{kmspc} -\title{MULTISPATI-PCA clustering} +\title{Spatial PCA-based fuzzy clustering (MULTISPATI-PCA)} \usage{ kmspc( data, @@ -20,50 +20,76 @@ kmspc( ) } \arguments{ -\item{data}{sf object} +\item{data}{an \code{sf} object with point geometries} -\item{variables}{variables to use for clustering, if missing, all numeric -variables will be used} +\item{variables}{\code{character} vector with variable names used for clustering. +If missing, all numeric variables in \code{data} are used.} -\item{number_cluster}{\code{numeric} vector with number of final clusters} +\item{number_cluster}{\code{numeric} vector indicating the number of clusters +to evaluate (e.g., \code{3:5})} -\item{explainedVariance}{\code{numeric} number in percentage of explained variance -from PCA analysis to keep and make cluster process} +\item{explainedVariance}{\code{numeric}. Percentage (0–100) of cumulative +explained spatial variance used to select spatial principal components. +Values between 0 and 1 are interpreted as proportions.} -\item{ldist}{\code{numeric} lower distance bound to identify neighbors} +\item{ldist, udist}{\code{numeric}. Lower and upper distance thresholds used +to define spatial neighbors.} -\item{udist}{\code{numeric} upper distance bound to identify neighbors} +\item{center}{centering option passed to PCA: +\describe{ + \item{TRUE}{center variables by their mean} + \item{FALSE}{no centering} + \item{numeric}{custom centering vector} +}} -\item{center}{a logical or numeric value, centring option -if TRUE, centring by the mean -if FALSE no centring -if a numeric vector, its length must be equal to the number of -columns of the data frame df and gives the decentring} +\item{fuzzyness}{\code{numeric} value greater than 1 controlling the degree of +fuzziness in clustering (see \code{e1071::cmeans})} -\item{fuzzyness}{A number greater than 1 giving the degree of fuzzification.} +\item{distance}{\code{character} distance metric for clustering. +One of \code{"euclidean"} or \code{"manhattan"} (abbreviations allowed)} -\item{distance}{\code{character} Must be one of the following: -If "euclidean", the mean square error, if "manhattan", the mean -absolute error is computed. Abbreviations are also accepted.} +\item{zero.policy}{Logical. If \code{TRUE}, allows empty neighbor sets; +if \code{FALSE}, stops with an error.} -\item{zero.policy}{default NULL, use global option value; -if FALSE stop with error for any empty neighbors sets, -if TRUE permit the weights list to be formed with zero-length -weights vectors} +\item{only_spca_results}{\code{logical}. If \code{TRUE}, only spatial PCA results +are returned. If \code{FALSE}, both PCA and spatial PCA summaries are included.} -\item{only_spca_results}{\code{logical}; should return both PCA and sPCA -results (\code{FALSE}), or only sPCA results (\code{TRUE})? This can be a -time consuming process if there are multiple variables.} - -\item{all_results}{\code{logical}; should return the results from the -sPCA and PCA call?} +\item{all_results}{\code{logical}. If \code{TRUE}, full PCA and spatial PCA +objects are returned (can increase computation time and memory use).} } \value{ -a list with classification results and indices to select best number of -clusters. +A list with the following elements: +\describe{ + \item{cluster}{\code{data.frame} with cluster assignments for each evaluated number of clusters} + \item{indices}{\code{data.frame} with clustering validity indices} + \item{summaryResults}{\code{data.frame} with clustering metrics (iterations, SSDW)} + \item{pca_results}{(optional) PCA and/or spatial PCA summaries depending on arguments} +} } \description{ -MULTISPATI-PCA clustering +Performs clustering of spatial data using a combination of spatial +Principal Component Analysis (PCA), and fuzzy k-means clustering. + +The workflow consists of: +\enumerate{ + \item Dimensionality reduction using spatial PCA + \item Selection of components based on explained spatial variance + \item Fuzzy clustering over selected components +} +} +\details{ +Spatial relationships are defined using distance-based neighbors +(\code{spdep::dnearneigh}). These relationships are incorporated into the +spatial PCA analysis to extract spatially structured components. + +Clustering is performed using fuzzy c-means over selected spatial components. +Several indices are computed to help determine the optimal number of clusters: +\itemize{ + \item Xie-Beni index + \item Partition coefficient + \item Partition entropy + \item Summary index (normalized combination) +} } \examples{ library(sf)