2. Tu primera herramienta
Introducción
Un script R para Processing R Provider no es diferente que un script normal de R. Las pequeñas diferencias entre ambos son simplemente estructuras lógicas para que el complemento en QGIS pueda interpretarlos correctamente. A continuación se listan las particularidades de los R scripts para QGIS:
- Tienen la extensión
.rsx
y pueden estar acompañados de un fichero de ayuda de extensión.rsx.help
. - Tienen por lo menos dos secciones importantes, un encabezado y un cuerpo, que se repasan en un sección posterior.
- Tanto el
.rsx
como el.rsx.help
deben estar en un directorio predefinido en la configuración del complemento.
Todas las instrucciones de R que se escriban en el script serán internamente reescritas en un Rscript (.r
|.R
) temporal que será ejecutado en la consola de R.
Estructura de un script
Un script R para processing tiene dos partes principales. Un encabezado que contiene la configuración de la herramienta; y un cuerpo que contiene el código R que ejecutará el proceso. El ejemplo que estudiaremos a continuación es tomado de los scripts incorporados en la instalación del complemento Processing R provider.
1##Example scripts=group
2##Scatterplot=name
3##Layer=vector
4##X=Field Layer
5##Y=Field Layer
6##output_plots_to_html
7
8# simple scatterplot
9plot(Layer[[X]], Layer[[Y]])
Las líneas que empiezan con doble signo numeral (##
) conforman el encabezado del script. Por ejemplo: ##Layer=vector
. Debe diferenciarse las líneas de encabezado (##
) y de las líneas de comentarios (#
) de modo que no causen confusión al algoritmo de Processing R Prvider. En tal caso, para los comentarios se recomienda usar un solo signo numeral #
cuando este empieza en una línea nueva: Por ejemplo # simple scatterplot
.
Las líneas de encabezado serán internamente convertidas en instrucciones de distintos tipos para que funcionen correctamente como una herramienta. Estas líneas condicionarán la estructura de la interfaz de la herramienta y el comportamiento de la misma.
Una línea de encabezado está conformada por dos partes: Identificador y Tipo.
1##nombre_parametro=tipo [valor_por_defecto/desde_variable]
...del script anterior podemos tomar cualquiera de las cinco primeras líneas como ejemplo, y veremos que tiene la estructura mencionada. Sin embargo algunos parámetros del encabezado pueden estar conformados simplemente por una etiqueta (por ejemplo ##output_plots_to_html
) que se usan internamente para indicar comportamientos específicos de la herramienta. Más detalles se verá en una sección posterior.
Los comentarios y las demás instrucciones de R no forman parte del encabezado, por lo tanto serán consideradas como cuerpo del script. Estas líneas serán transcritas a un Rscript temporal, que será ejecutado línea por línea en la consola de R, mediante un subproceso stdin/stdout.
Tipos de parámetros
El encabezado puede contener distintos tipos de parámetros. Y de acuerdo con ellos la herramienta se comportará de una forma u otra:
Metadatos
Son parámetros que permiten organizar el script en el índice de processing. Entre ellos tenemos:
name
Permite definir un nombre corto para el scriptdisplay_name
Permite definir un nombre largo para el script. Este se mostrará en el índice y en la barra de título de la herramientagroup
nombre del grupo al que pertenece el script. Permite organizar la nueva herramienta como parte de un grupo específico de herramientas.
1##Example scripts=group
2##Scatterplot=name
3##Scatterplot from selected fields=display_name
Parámetros de comportamiento
Sirven para definir el comportamiento general del script. Estos parámetros se configuran en el encabezado, pero el usuario no interactúa con estos. Entre ellos tenemos
load_raster_using_rgdal
load_vector_using_rgdal
pass_filenames
dont_load_any_packages
github_install
expression
output_plots_to_html
Parámetros de entrada
Estas líneas de parámetros especifican la apariencia de la interfaz del script. A partir de la estructura básica ##nombre_parametro=tipo [valor_por_defecto/desde_variable]
podemos destacar que nombre_parámetro
será el nombre del objeto que contenga esa variable en la sesión de R. Mientras que tipo
será el tipo de datos de entrada, de los posibles tipos de entrada (vector, raster, point, number, string, boolean, Field).
Parámetro | Valor por defecto | Desde variable |
---|---|---|
vector |
Si | No |
raster |
Si | No |
point |
Si | No |
number |
Si | No |
string |
Si | No |
boolean |
Si | No |
Field |
No | definida en vector |
color |
Si | No |
range |
Si | No |
datetime |
Si | No |
Band |
No | definida en raster |
extent |
No | No |
crs |
No | No |
enum |
No | No |
enum literal |
No | No |
Parámetros de salida
Se trata de líneas que permiten definir el tipo de resultado que tendrá el script. Visualmente estos parámetros generan interfaces gráficas para guardar ficheros, mientras que internamente se traducen como instrucciones para escribir objetos R como ficheros.
La especificación de estos parámetros es la siguiente:
1##<Nombre_de_salida> =output <tipo>
Entre las salidas posibles tenemos las siguientes:
- Salidas de capas:
vector
,raster
,table
- Salidas de valores:
string
number
- Directorios y ficheros:
folder
yfile
. El el caso de file, se puede especificar una extensión para el fichero de salida. Por ejemplocsv
.
Opcionalmente se puede usar la palabra clave noprompt
al final de cada parámetro de salida, para especificar que no genere el widget en la interfaz de la herramienta.
Ejercicio
Imagina que tienes una capa de puntos de donde necesitas calcular distintas medidas de tendencia central espacial. Tus datos están cargados en la sesión de QGIS, pero QGIS no tiene una herramienta que te permita calcular puntos centrales a partir de tus datos.
El ejercicio consiste en hacer una herramienta para QGIS que haga el cálculo del punto central, con diferentes estadísticos. Por ejemplo, "Mean center", "Median center", "Central feature" o "Weighted mean center" (ver más detalles).
Tiempo de intentarlo, tómate un tiempo de 3 minutos para analizar el siguiente código de R. Las porciones de código entre los signos <
y >
corresponden a los nombres de variables de los parámetros de entrada. Los signos <
y >
no son necesarios en un script válido, solo se han usado para resaltar el ejemplo.
1# Funciones y objetos para calcular punto medio ----
2
3 # < Aquí el código de 4 funciones de ayuda para el cálculo. >
4 # < no son importantes por ahora. >
5
6# Calcular punto medio ----
7 # extraer matriz de coordenadas de los puntos ----
8 xy <- st_coordinates(< CAPA >)
9
10 # Control para el campo de pesos ----
11 < CAMPO DE PESOS > <- if(!is.null(< CAMPO DE PESOS >)) < CAPA >[[< CAMPO DE PESOS >]]
12
13 # obtener el punto medio ----
14 mc <- switch(< CENTRO ESPACIAL >,
15 mean.center = mean_mc(),
16 weighted.mean.center = mean_mc(< CAMPO DE PESOS >),
17 median.center = median_mc(),
18 central.feature = central_feature(),
19 all = all_features()
20 )
21
22 # Convertir a Simple Feature y asignar CRS ----
23 < PUNTO CENTRAL > <- st_as_sf(st_geometry(mc), crs = st_crs(< CAPA >))
24
25 # Asignar nombres como atributos del punto medio ----
26 < PUNTO CENTRAL >$Name <- if(< CENTRO ESPACIAL > == "all") nms else nms[< CENTRO ESPACIAL >]
27
Cuando estés listo:
-
Crea un nuevo script para QGIS Processing desde
/Create New R Script
. -
Escribe el encabezado de tu script para QGIS Processing, basándote en el código de R que revisaste
- Empieza asignando un nombre al script con el parámetro
name
- Agrega un grupo al script con el parámetro
group
- Opcionalmente, también se puede agregar el parámetro
display_name
para poner un título más explicativo para la herramienta. - Agrega un parámetro para una capa vectorial de tipo punto usando el parámetro
vector point
- Agrega una lista desplegable (
enum literal
) con las opciones de selecciónall;mean.center;weighted.mean.center;median.center;central.feature
. Nótese que cada elemento de la lista está separado por un punto y coma (;). - Agrega un parámetro para campo de pesos opcional que se despliegue desde la capa vectorial, mediante el parámetro
Field
seguido del nombre de la variable que asignaste en el parámetro de la capa de entrada. - Agrega el nombre de la capa de saluda usando el parámetro
output vector
.
- Empieza asignando un nombre al script con el parámetro
-
Copia y pega el código R que te mostramos a continuación, en tu nuevo script:
Clic aquí para ver el código completo y funcional de este mismo ejercicio.
1# Funciones y objetos para calcular punto medio ---- 2nms <- c(mean.center = "Mean center", 3 median.center = "Median center", 4 central.feature = "Central feature", 5 weighted.mean.center = "Weighted mean center") 6 7mean_mc <- function(w = NULL){ 8 if(is.null(w) && Centro_espacial == "weighted.mean.center") 9 warning("Weights field is null. Mean center instead!") 10 11 if(!is.null(w)) { 12 m <- apply(xy, 2, weighted.mean, w = w) 13 } else {m <- apply(xy, 2, mean)} 14 st_point(m) 15 } 16 17median_mc <- function() st_point(apply(xy, 2, median)) 18 19central_feature <- function(){ 20 d <- st_distance(Capa) 21 d <- apply(d, 1, sum) 22 st_point(xy[which.min(d),]) 23} 24 25all_features <- function(){ 26 if(!is.null(Campo_de_pesos)) 27 st_sfc(mean_mc(), median_mc(), central_feature(), mean_mc(Campo_de_pesos)) 28 else 29 st_sfc(mean_mc(), median_mc(), central_feature()) 30} 31 32# Calcular punto medio ---- 33 # extraer matriz de coordenadas de los puntos ---- 34 xy <- st_coordinates(Capa) 35 # Control para el campo de pesos ---- 36 Campo_de_pesos <- if(!is.null(Campo_de_pesos)) Capa[[Campo_de_pesos]] 37 # obtener el punto medio ---- 38 mc <- switch(Centro_espacial, 39 mean.center = mean_mc(), 40 weighted.mean.center = mean_mc(Campo_de_pesos), 41 median.center = median_mc(), 42 central.feature = central_feature(), 43 all = all_features() 44 ) 45 # Convertir a Simple Feature y asignar CRS ---- 46 Punto_central <- st_as_sf(st_geometry(mc), crs = st_crs(Capa)) 47 # Asignar nombres como atributos del punto medio ---- 48 Punto_central$Name <- if(Centro_espacial == "all") nms else nms[Centro_espacial]
-
Finalmente guarda tu script en el directorio de scripts definido en la configuración del complemento.
El contenido a continuación ha sido ocultado intencionalmente. Despliégalo solo si sientes que no puedes realizar el ejercicio por tu cuenta.
Haz clic para mostrar el contenido de ayuda.
1##Taller UseR!2022=group
2##centrality=name
3##Centralidad espacial=display_name
4##Capa=vector point
5##Centro_espacial=enum literal all
6##Campo_de_pesos=optional field Capa
7##Punto_central=output vector
8
9# FUNCIONES Y OBJETOS AUXILIARES PARA CALCULAR PUNTO MEDIO ----
10nms <- c(mean.center = "Mean center",
11 median.center = "Median center",
12 central.feature = "Central feature",
13 weighted.mean.center = "Weighted mean center")
14
15mean_mc <- function(w = NULL){
16 if(is.null(w) && Centro_espacial == "weighted.mean.center")
17 warning("Weights field is null. Mean center instead!")
18
19 if(!is.null(w)) {
20 m <- apply(xy, 2, weighted.mean, w = w)
21 } else {m <- apply(xy, 2, mean)}
22 st_point(m)
23}
24
25median_mc <- function() st_point(apply(xy, 2, median))
26
27central_feature <- function(){
28 d <- st_distance(Capa)
29 d <- apply(d, 1, sum)
30 st_point(xy[which.min(d),])
31}
32
33all_features <- function(){
34 if(!is.null(Campo_de_pesos))
35 st_sfc(mean_mc(), median_mc(), central_feature(), mean_mc(Campo_de_pesos))
36 else
37 st_sfc(mean_mc(), median_mc(), central_feature())
38}
39
40# CALCULAR PUNTO MEDIO ----
41# extraer matriz de coordenadas de los puntos ----
42xy <- st_coordinates(Capa)
43
44# Control para el campo de pesos ----
45Campo_de_pesos <- if(!is.null(Campo_de_pesos)) Capa[[Campo_de_pesos]]
46
47# obtener el punto medio ----
48mc <- switch(Centro_espacial,
49 mean.center = mean_mc(),
50 weighted.mean.center = mean_mc(Campo_de_pesos),
51 median.center = median_mc(),
52 central.feature = central_feature(),
53 all = all_features()
54)
55
56# Convertir a Simple Feature y asignar CRS ----
57Punto_central <- st_as_sf(st_geometry(mc), crs = st_crs(Capa))
58
59# Asignar nombres como atributos del punto medio ----
60Punto_central$Name <- if(Centro_espacial == "all") nms else nms[Centro_espacial]
61