<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>GIS &#38; Chips &#187; pl/R</title>
	<atom:link href="http://www.gisandchips.org/tag/plr/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gisandchips.org</link>
	<description>Geografía útil para llevar</description>
	<lastBuildDate>Tue, 29 Nov 2011 10:38:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>La ciencia de los suelos (I). Creación de triángulos texturales directamente desde una Geodatabase.</title>
		<link>http://www.gisandchips.org/2010/09/08/la-ciencia-de-los-suelos-i-creacion-de-triangulos-texturales-directamente-desde-una-geodatabase/</link>
		<comments>http://www.gisandchips.org/2010/09/08/la-ciencia-de-los-suelos-i-creacion-de-triangulos-texturales-directamente-desde-una-geodatabase/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 04:44:54 +0000</pubDate>
		<dc:creator>benizar</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[gráficas]]></category>
		<category><![CDATA[pl/R]]></category>
		<category><![CDATA[PostGIS]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[R]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=1629</guid>
		<description><![CDATA[Llevo un tiempo ocupado pero ya es hora de enseñar en GIS&#38;Chips algunas de las demos que realicé para mi Trabajo Fin de Master (TFM) sobre SIG. En este artículo os muestro la demo nº2 que consiste en la creación de triángulos texturales directamente desde una Geodatabase que diseño y creo previamente dentro del TFM. [...]]]></description>
			<content:encoded><![CDATA[<p>Llevo un tiempo ocupado pero ya es hora de enseñar en GIS&amp;Chips algunas de las demos que realicé para mi Trabajo Fin de Master (TFM) sobre SIG.</p>
<p>En este artículo os muestro la demo nº2 que consiste en la creación de triángulos texturales directamente desde una <strong>Geodatabase </strong>que diseño y creo previamente dentro del TFM. Pero más adelante añadiré algunos comentarios de las otras demos.</p>
<div id="attachment_1630" class="wp-caption aligncenter" style="width: 277px"><a href="http://www.gisandchips.org/wp-content/clasificacion_textural.png"><img class="size-medium wp-image-1630" src="http://www.gisandchips.org/wp-content/clasificacion_textural-267x300.png" alt="" width="267" height="300" /></a><p class="wp-caption-text">Triángulo textural</p></div>
<h3><span id="more-1629"></span>El TFM</h3>
<p>Es interesante comentar que el TFM es una pequeña parte de otra investigación que estoy realizando en el contexto de la comarca de la Marina Baja (Alicante-España) y los datos que se muestra en las distintas demos son parte de un muestreo para entender mejor el potencial nutritivo de los suelos de la comarca.</p>
<p>El título del TFM es “Diseño de una base de datos geográfica orientada al estudio de los suelos”. Evidentemente, en el espacio de un TFM no cabía desarrollar toda la idea, que podría ser muy trabajosa para una sola persona, del mismo modo que aquí no cabe desarrollar todo el TFM ya que hay algunas partes que no tienen que ver con lo que queremos contar en G&amp;C.</p>
<p>Si entráis en la página principal del la Web de demostraciones podéis leer un poco más sobre la intención y contenidos del TFM ( <a href="http://www.gisandchips.org/demos/suelosTFM/">http://www.gisandchips.org/demos/suelosTFM/</a> ). Además en esta página se explican los detalles de la tecnología utilizada y del método de trabajo (<strong>PostgreSQL</strong>, <strong>PostGIS</strong>, R, <strong>pl/R</strong>&#8230;).</p>
<p>Considero que las demos 2 y 3 son más interesantes, puesto que la primera es solo una función de clasificación que cada uno podría hacer a su gusto, pero si a alguien le interesa la explicaré más adelante.</p>
<div id="attachment_1645" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gisandchips.org/wp-content/tritex_1.jpg"><img class="size-medium wp-image-1645" src="http://www.gisandchips.org/wp-content/tritex_1-300x232.jpg" alt="" width="300" height="232" /></a><p class="wp-caption-text">Página de la Demo</p></div>
<h3>Los triángulos texturales</h3>
<p>El estudio de los suelos es una disciplina tremendamente amplia, por lo que aquí nos limitaremos a dar, de un modo más breve, las explicaciones necesarias para entender los gráficos resultantes.</p>
<p>Los <strong>triángulos texturales</strong> son gráficos que facilitan la interpretación de la granulometría del suelo. Así pues, habitualmente la textura del suelo se puede representar en un diagrama ternario. En dicho diagrama ternario se emplean reglas trigonométricas para representar en el plano coordenadas tridimensionales que se refieren a distintas combinaciones de clases granulométricas (clases texturales) cuya suma es constante (100). Por último, las clases texturales son convenientes para representar a la textura del suelo en mapas ya que resulta más sencillo representar una variable que no tres, y su uso es bastante amplio en descripciones y clasificaciones del suelo.</p>
<p>A pesar de todas las ventajas de estos gráficos, aparece la dificultad de que existen gran número de triángulos texturales que permiten la clasificación de los suelos, lo que implica que en caso de querer incluir herramientas relacionadas en una BDGS (Geodatabase de suelos) se deba considerar tal variedad de criterios. En este caso se ha creado un gráfico de texturas según las especificaciones del USDA (1951) en castellano.</p>
<p>Pese a que existe cierta variedad de programas pensados para la elaboración de los triángulos de texturas parece interesante que una BDGS que almacene los datos de textura de suelos sea capaz de generar este tipo de gráficos. Además, los otros software suelen ser difíciles de encontrar y poco flexibles. Aquí podemos modificar nuestro gráfico a placer.</p>
<div id="attachment_1643" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gisandchips.org/wp-content/tritex_results.jpg"><img class="size-medium wp-image-1643" src="http://www.gisandchips.org/wp-content/tritex_results-300x188.jpg" alt="" width="300" height="188" /></a><p class="wp-caption-text">Página de resultados de la demo</p></div>
<h3>Demostración  Triángulo Textural</h3>
<p>En la propia página Web (<a href="http://www.gisandchips.org/demos/suelosTFM/paginas/demo_tritex1.php">http://www.gisandchips.org/demos/suelosTFM/paginas/demo_tritex1.php</a> ) se explica como interactuar con la demo, seleccionando las muestras que se desee, si se desea etiquetar las muestras y con que símbolo se van a representar. Como se puede ver, los datos han sido previamente ordenados según una consulta espacial usando funciones de <strong>PostGIS</strong>, por lo que la gráfica que vamos a generar se ve enriquecida por esta posibilidad. A partir de los datos seleccionados se ejecuta una función escrita en pl/R que usa la librería &#8220;Plotrix&#8221; de R para generar un triángulo textural personalizado y guardarlo como un fichero PNG en el servidor. La función que se usa en este ejemplo puede ser personalizada en muchos sentidos para obtener otros triángulos texturales (hay decenas), en otros idiomas, clasificando los símbolos por algún atributo de la base de datos&#8230;</p>
<p>El uso de la función resulta muy sencillo,</p>
<pre class="brush: sql; title: ; notranslate">
SELECT  _plr_clasif_textural ( 'arenas' , 'limos' , 'arcilla' , 'submuestra' , 'simbolo' , 'etiquetas') ;
</pre>
<p>y a continuación podemos ver el código que hemos usado para crearla, y algunos comentarios:</p>
<pre class="brush: sql; title: ; notranslate">
-- Function: _plr_clasif_textural(text, text, text, text, text, text)
-- DROP FUNCTION _plr_clasif_textural(text, text, text, text, text, text);
CREATE OR REPLACE FUNCTION _plr_clasif_textural(text, text, text, text, text, text)
RETURNS text AS
$BODY$
</pre>
<pre class="brush: bash; title: ; notranslate">
# Cargamos las librerias necesarias
library(Cairo)
library(plotrix)
# Definimos la funcion
clasif.textural = function (soiltexture = NULL, at = seq(0.1, 0.9, by = 0.1),
axis.labels = c(&quot;% arena (entre 0,05 y 2 mm)&quot;, &quot;% limo (entre 0,05 y 0,002 mm)&quot;, &quot;% arcilla (menor de 0,002  mm)&quot;),
tick.labels = list(l = seq(10, 90, by = 10), r = seq(10,
90, by = 10), b = seq(10, 90, by = 10)), show.names = TRUE,
show.lines = TRUE, col.names = &quot;black&quot;, bg.names = par(&quot;bg&quot;),
show.grid = TRUE, col.axis = &quot;black&quot;, col.lines = &quot;black&quot;,
col.grid = &quot;gray&quot;, lty.grid = 3, show.legend = FALSE, label.points = FALSE,
point.labels = '', col.symbols = &quot;blue&quot;, pch = par(&quot;pch&quot;),
...)
{
par(xpd = TRUE)
plot(0.5, type = &quot;n&quot;, axes = FALSE, xlim = c(0, 1), ylim = c(0,
1), main = NA, xlab = NA, ylab = NA)
triax.frame(at = at, axis.labels = axis.labels,
tick.labels = tick.labels, col.axis = col.axis, show.grid = show.grid,
col.grid = col.grid, lty.grid = lty.grid)
arrows(0.12, 0.41, 0.22, 0.57, length = 0.15)
arrows(0.78, 0.57, 0.88, 0.41, length = 0.15)
arrows(0.6, -0.1, 0.38, -0.1, length = 0.15)
if (show.lines) {
triax.segments &lt;- function(h1, h3, t1, t3, col) {
segments(1 - h1 - h3/2, h3 * sin(pi/3), 1 - t1 -
t3/2, t3 * sin(pi/3), col = col)
}
h1 &lt;- c(85, 70, 80, 52, 52, 50, 20, 8, 52, 45, 45, 65,
45, 20, 20)/100
h3 &lt;- c(0, 0, 20, 20, 7, 0, 0, 12, 20, 27, 27, 35, 40,
27, 40)/100
t1 &lt;- c(90, 85, 52, 52, 43, 23, 8, 0, 45, 0, 45, 45,
0, 20, 0)/100
t3 &lt;- c(10, 15, 20, 7, 7, 27, 12, 12, 27, 27, 55, 35,
40, 40, 60)/100
triax.segments(h1, h3, t1, t3, col.lines)
}
if (show.names) {
xpos &lt;- c(0.5, 0.7, 0.7, 0.73, 0.73, 0.5, 0.275, 0.275,
0.27, 0.27, 0.25, 0.135, 0.18, 0.07, 0.49, 0.72,
0.9)
ypos &lt;- c(0.66, 0.49, 0.44, 0.36, 0.32, 0.35, 0.43, 0.39,
0.3, 0.26, 0.13, 0.072, 0.032, 0.024, 0.18, 0.15,
0.06) * sin(pi/3)
snames &lt;- c(&quot;arcillosa&quot;, &quot;arcillosa&quot;, &quot;limosa&quot;, &quot;franco arcillosa&quot;, &quot;limosa&quot;,
&quot;franco arcillosa&quot;, &quot;arcillosa&quot;, &quot;arenosa&quot;, &quot;franco arcillosa&quot;, &quot;arenosa&quot;,
&quot;franco arenosa&quot;, &quot;arenosa&quot;, &quot;franca&quot;, &quot;arenosa&quot;, &quot;franca&quot;, &quot;franco limosa&quot;,
&quot;limosa&quot;)
boxed.labels(xpos, ypos, snames, border = FALSE, col = col.names,
cex=0.8, xpad = 0.5)
}
par(xpd = FALSE)
if (is.null(soiltexture))
return(NULL)
soilpoints &lt;- triax.points(soiltexture, show.legend = show.legend,
label.points = label.points, point.labels = point.labels,
col.symbols = col.symbols, pch = pch, ...)
invisible(soilpoints)
}
# Definimos la imagen
CairoPNG(&quot;…/images/clasificacion_textural.png&quot;, width=500, height=560)
# Construimos las consultas
select = 'select '
arena = paste(arg1, ',', sep=' ');
limo = paste(arg2, ',', sep=' ');
arcilla = paste(arg3, ' ');
from = ' from '
tabla = arg4
selection = paste(select, arena, limo, arcilla, from, tabla, sep='');
selectgids = paste('select gid', from, tabla, sep='');
# Ejecutamos las consultas
texturas &lt;- pg.spi.exec(selection)
gids&lt;- pg.spi.exec(selectgids)
# Ejecutamos la funcion creada mas arriba
soiltex.return&lt;-clasif.textural(texturas,
pch=arg5, point.labels = gids[,], label.points=arg6)
dev.off()
# Damos permisos de lectura
system('chmod go+r …/images/clasificacion_textural.png');
# Una comprobacion para asegurarnos de que se ha creado la grafica, pero no afecta para nada.
if (file.exists('…/images/clasificacion_textural.png')) {
print ('Grafico realizado. Se llama …/images/clasificacion_textural.png')};
</pre>
<pre class="brush: sql; title: ; notranslate">
$BODY$
LANGUAGE 'plr' VOLATILE
COST 100;
ALTER FUNCTION _plr_clasif_textural(text, text, text, text, text, text) OWNER TO postgres;
</pre>
<h3>Algunas notas sobre todo esto:</h3>
<p>(1) En el TFM se apunta que en breve aparecerá una librería creada por Julien Moeys ( <a href="https://r-forge.r-project.org/projects/soiltexture/">https://r-forge.r-project.org/projects/soiltexture/</a> ) que hará innecesario tener que crear la función por nosotros mismos como hemos hecho en esta demostración. Será interesante comentar con los miembros del proyecto la posibilidad de compartir las funciones de su proyecto en una Web completamente dedicada al cálculo de triángulos texturales, donde los usuarios puedan añadir sus propios datos.</p>
<p>(2) Los datos de ejemplo están un poco modificados pero se aproximan a la realidad.</p>
<p>(3) La función tiene muchos aspectos mejorables, por lo menos en cuanto a la legibilidad. Otra posibilidad sería la de que no todos los argumentos de entrada fuesen de tipo texto. Esto lo veremos plasmado en el código de la demo 3.</p>
<p>(4) Si en la página  inicial de la demo no se ve una lista con las muestras disponibles (como en la segunda imagen) será porqué el servidor de la base de datos ha caído y lo deberemos reiniciar en breve. Solo ha pasado una vez, pero quien sabe…</p>
<p>(5) Este artículo destaca la potencia de pl/R a la hora de crear gráficos de lo más complejos.</p>
<h3>Agradecimientos:</h3>
<p>El TFM de que he estado hablando ha sido dirigido por Toni Hernández, en el Máster en Sistemas de Información Geográfica y Teledetección de la Universitat de Girona (UNIGIS), y fue presentado en Mayo de 2010. Les estoy muy agradecido a todos los miembros, tanto alumnos como profesores, por estos últimos años disfrutando y aprendiendo SIG.</p>
<p>Especialmente, quiero agradecer a los compañeros de G&amp;C por la ayuda con instalaciones, creación de la Web y otros dolores de cabeza.</p>
<p>——————————————————————</p>
<p>Si queréis contactar podéis enviarme un email (asunto: gisandchips):</p>
<p>Benito M. Zaragozí</p>
<p>benito.zaragozi@ua.es</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2010/09/08/la-ciencia-de-los-suelos-i-creacion-de-triangulos-texturales-directamente-desde-una-geodatabase/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cartografía temática II: Cálculo de intervalos de clase con PL/R</title>
		<link>http://www.gisandchips.org/2010/02/04/cartografia-tematica-ii-calculo-de-intervalos-de-clase-con-plr/</link>
		<comments>http://www.gisandchips.org/2010/02/04/cartografia-tematica-ii-calculo-de-intervalos-de-clase-con-plr/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 14:53:22 +0000</pubDate>
		<dc:creator>jose</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[cartografía temática]]></category>
		<category><![CDATA[mapscript]]></category>
		<category><![CDATA[pl/R]]></category>
		<category><![CDATA[R]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=1380</guid>
		<description><![CDATA[Como ya vimos en la primera parte de esta mini-serie dedicada a la cartografía temática, hasta ahora sólo tenemos resuelta una parte, la asignación de paletas de colores para nuestros mapas o semiología cartográfica, pero queda otra parte por resolver, la lógica estadística, es decir, calcular cuales serán los valores de cada uno de los [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1416" class="wp-caption aligncenter" style="width: 310px"><a href="/demos/j3m/plr/test5.php"><img class="size-medium wp-image-1416" src="http://www.gisandchips.org/wp-content/madrid-300x228.png" alt="Población por municipios de Madrid (2008)" width="300" height="228" /></a><p class="wp-caption-text">Población por municipios de Madrid (2008) </p></div>
<p>Como ya vimos en la <a href="http://www.gisandchips.org/2010/02/04/cartografia-tematica-i-phpcolorbrewer/">primera parte</a> de esta mini-serie dedicada a la cartografía temática, hasta ahora sólo tenemos resuelta una parte, la asignación de paletas de colores para nuestros mapas o semiología cartográfica, pero queda otra parte por resolver, la lógica estadística, es decir, calcular cuales serán los valores de cada uno de los intervalos de clase que intervienen en una distribución numérica.<br />
<span id="more-1380"></span><br />
Como ya es habitual en<a href="http://www.gisandchips.org"> </a><a href="http://www.gisandchips.org">www.gisandchips.org</a> tenemos una especial predilección por almacenar nuestra fuente de datos en tablas espaciales contenidas en una base de datos PostgreSQL-PostGIS, y esta vez no va a ser menos.</p>
<p>Generalmente, el cálculo de los puntos de ruptura de una distribución ha sido tratado habitualmente desde el punto de vista del cliente (<em>gvSIG, Quantum GIS, ArcGIS</em>, etc), descargándose a la aplicación  los datos oportunos (shapefiles, PostGIS, etc) para escoger posteriormente algún método de agrupamiento o clustering. Esta solución resulta apropiada cuando los datos a representar proceden de diferentes fuentes, cambios de geometría constantes realizamos muchos temáticos distintos, o cualquier otra variable a considerar. Pero sin embargo, cuando necesitamos representar la misma realidad espacial (municipios, provincias, comunidades autónomas, continentes, etc) desde diferentes aspectos (demografía, economía, agriculturas, etc) no resulta tán cómodo delegar esta función a la aplicación cliente.</p>
<p>Pongamos un ejemplo para clarificar el tema: Imaginemos que disponemos de datos de población agregados a nivel de municipios, donde existen tantas columnas como censos de población se hayan hecho, y deseamos generar en un portal de Internet mapas temáticos a requerimiento del usuario (año del censo, nº de clases, método de agrupamiento o <em>clustering </em>y paleta de colores). Crear un mapa coroplético de la población lleva implícito un conocimiento de la distribución de los datos (valores mínimos y máximos de la serie, media), y sobre todo las medidas de dispersión o de variabilidad: desviación típica, varianza, co-varianza, coeficiente de correlación de Pearson. Con estos parámetros estamos en condiciones de definir cual será el método de cálculo de intervalo de clase más apropiado para nuestra distribución, para posteriormente asignar la paleta de colores acorde al fenómeno a representar (este último aspecto ya lo tenemos solucionado con nuestra clase PHPcolorBrewer). Con una aplicación de GIS de escritorio sólo podemos realizar un mapa para visualizarlo en pantalla o imprimirlo, pero en un ambiente web(GIS) este forma de actuar carece de lógica, pues estamos limitando al usuario la posibilidad de elegir estos parámetros (método de clustering, número de clases y paleta de colores), ya que es muy complicado obtener datos de un GIS y realizar los cálculos de los intervalos de clases en la própia página web (<em>JavaScript, PHP</em>).</p>
<div id="attachment_1432" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gisandchips.org/wp-content/plr.png"><img class="size-medium wp-image-1432" src="http://www.gisandchips.org/wp-content/plr-300x175.png" alt="Flujo cartografía temática" width="300" height="175" /></a><p class="wp-caption-text">Flujo cartografía temática</p></div>
<p>En este artículo vamos a solucionar esta cuestión proponiendo un método que nos permita desde el servidor, es decir, desde el gestor de base de datos, calcular los intervalos de clase. Para ello no nos queda más remedio que recurrir a la creación de funciones o procedimientos almacenados que contemplen dicha lógica. Realizarlo con <em>PLPg/SQL</em> es una solución, pero programar estas funciones requiere de mucho esfuerzo al no formar parte de las funciones nativas del servidor (por ejemplo, no existe una función que calcule la desviación típica). ¿Por qué no utilizamos un lenguaje especializado en el manejo estadístico? En este sentido, <em><strong>PL/R</strong></em> reúne todas las condiciones para convertirse en el lenguaje de programación elegido. Una prueba de la potencia de este lenguaje, en este caso <strong>R</strong> lo podemos ver con este ejemplo.</p>
<p><strong>Implementación en R</strong><br />
Tenemos la población activa (valores en miles) de todas las provincias españolas, obtenidas del INE, en el año 1996, disponibles en un objeto vector:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="576" valign="top">c(126.4,137.9,570.9,192.1,409.7,60.2,251.3,325.9,2109.1,145.8,159.4,425.5,207.8,194.3,<br />
172.5,301.5,443,69,252.4,300,55.2,296.4,158.2,84.5,244.3,200.3,141.7,174.2,2180.7,<br />
475.8,438,224.6,161.4,71.2,320.8,390,104.7,144.3,328.3,56.5,646.5,36.3,242,52.8,196.5,<br />
919.6,211.6,473.9,70.2,356.7,50)</td>
</tr>
</tbody>
</table>
<p>En una sesión de R se crearía de esta manera</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="576" valign="top">poblacion.1996 &lt;- c(126.4,137.9,570.9,192.1,409.7,60.2,251.3,325.9,2109.1,145.8,159.4,<br />
425.5,207.8,194.3,172.5,301.5,443,69,252.4,300,55.2,296.4,158.2,84.5,244.3,200.3,141.7,<br />
174.2,2180.7,475.8,438,224.6,161.4,71.2,320.8,390,104.7,144.3,328.3,56.5,646.5,36.3,<br />
242,52.8,196.5,919.6,211.6,473.9,70.2,356.7,50)</td>
</tr>
</tbody>
</table>
<p>Y se podría ver simplemente escribiendo:</p>
<pre class="brush: bash; title: ; notranslate">poblacion.1996</pre>
<p>Resultado</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="576" valign="top">[1]  126.4  137.9  570.9  192.1  409.7   60.2  251.3  325.9 2109.1  145.8<br />
[11]  159.4  425.5  207.8  194.3  172.5  301.5  443.0   69.0  252.4  300.0<br />
[21]   55.2  296.4  158.2   84.5  244.3  200.3  141.7  174.2 2180.7  475.8<br />
[31]  438.0  224.6  161.4   71.2  320.8  390.0  104.7  144.3  328.3   56.5<br />
[41]  646.5   36.3  242.0   52.8  196.5  919.6  211.6  473.9   70.2  356.7<br />
[51]   50.0</td>
</tr>
</tbody>
</table>
<p>Para ver un sumario estadístico básico de dicho objeto escribimos:</p>
<pre class="brush: bash; title: ; notranslate">summary(poblacion.1996)</pre>
<p>Con este resultado:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="576" valign="top">Min. 1st Qu.  Median    Mean 3rd Qu.    Max.<br />
36.3   139.8   207.8   320.8   342.5  2181.0</td>
</tr>
</tbody>
</table>
<p>Entrando ya en materia, vamos a calcular 5 clases distribuidas por el método de intervalos iguales, es decir, <em>(valor máximo- valor mínimo) / nº intervalos</em>:</p>
<pre class="brush: bash; title: ; notranslate">seq(min(poblacion.1996),max(poblacion.1996),length.out=(5+1))</pre>
<p>Resultado</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="576" valign="top">[1]   36.30  465.18  894.06 1322.94 1751.82 2180.70</td>
</tr>
</tbody>
</table>
<p>Es decir, las clases quedarían agrupadas de esta forma:</p>
<ul>
<li>clase 1: 36.30 &#8211; 465.18</li>
<li>clase 2: 465.18 &#8211; 894.06</li>
<li>clase 3: 894.06 &#8211; 1322.94</li>
<li>clase 4: 1322.94 &#8211; 1751.82</li>
<li>clase 5: 1751.82 &#8211; 2180.70</li>
</ul>
<p>Este método, aunque sencillo de implementar (incluso desde la parte cliente) ofrece una clasificación muy distorsionada cuando los valores son muy dispares, por lo que necesitamos recurrir a otros métodos más eficientes, como son los cuantiles. En R este cálculo queda reducido a la mínima expressión:</p>
<pre class="brush: bash; title: ; notranslate">quantile(poblacion.1996)</pre>
<p>Resultado:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="576" valign="top">0%    25%    50%    75%   100%<br />
36.3  139.8  207.8  342.5 2180.7</td>
</tr>
</tbody>
</table>
<p>Esta sería nuestra clasificación</p>
<ul>
<li>1º quantil: 36.3 &#8211; 139.8</li>
<li>2º quantil: 139.8 &#8211; 207.8</li>
<li>3º quantil: 207.8 &#8211; 342.5</li>
<li>4º quantil: 342.5 &#8211; 2180.7</li>
</ul>
<p>¡Más sencillo imposible!</p>
<p>El problema de trabajar directamente en R estriba en la dificultad para obtener datos desde otras fuentes, aunque siempre podemos recurrir a paquetes externos para traer los datos de shapefiles o tablas de PostgreSQL a R</p>
<p><strong>Implementación en PostgreSQL</strong></p>
<p>Como ya hemos visto en anteriores artículos sobre PL/R, esta lenguaje procedural es muy sencillo de utilizar. Sólo hay que copiar el código de R y realizar pequeños cambios para adaptarlo a la sintaxis de PL/R.</p>
<p>Un aspecto que debemos tener muy claro es que casi todos los cálculos en R de una distribución deben de estar dispuestos en forma de un vector. Como es lógico, PostgreSQL no soporta este tipo de dato, pero el lenguaje PL/R si que nos permite una conversión hacia el tipo de datos &#8220;array&#8221;, ofreciéndonos además una función que realiza todo el trabajo (<em>array_accum</em>)</p>
<p>Por ejemplo, si queremos obtener un array con los datos de la poblacion activa en 1996 (columna t1996t1) de la tabla ine.poblacion_activa, esta es la forma de conseguirlo con SQL:</p>
<pre class="brush: sql; title: ; notranslate">SELECT array_accum(t1996t1) FROM ine.poblacion_activa;</pre>
<p>Y este el resultado:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="576" valign="top">{126.4,137.9,570.9,192.1,409.7,60.2,251.3,325.9,2109.1,145.8,<br />
159.4,425.5,207.8,194.3,172.5,301.5,443,69,252.4,300,55.2,296.4,<br />
158.2,84.5,244.3,200.3,141.7,174.2,2180.7,475.8,438,224.6,161.4,<br />
71.2,320.8,390,104.7,144.3,328.3,56.5,646.5,36.3,242,52.8,196.5,<br />
919.6,211.6,473.9,70.2,356.7,50}</td>
</tr>
</tbody>
</table>
<p>Con esta pequeña aclaración ya podemos utilizar cualquier columna con datos numéricos para realizar funciones de clustering. Las siguientes funciones de PL/R reproducen los cálculos realizados anteriormente con R:</p>
<p>Función para el método de intervalos iguales:</p>
<pre class="brush: sql; title: ; notranslate">
CREATE OR REPLACE FUNCTION r_equal(double precision[], integer)
RETURNS double precision[] AS
$BODY$
sort(seq(min(arg1),max(arg1),length.out=(arg2+1)))

$BODY$
LANGUAGE 'plr' VOLATILE STRICT
COST 100;
</pre>
<p>Vamos a analizar esta función.</p>
<p>Tiene dos parámetros de entrada:</p>
<ul>
<li>double precision[]: El array con los datos de entrada que queremos utilizar para calcular los intervalos, utilizando la función array_accum</li>
<li>integer: el nº de intervalos de clase que deseamos obtener</li>
</ul>
<p>El resultado (RETURNS) será siempre una estructura de tipo array.<br />
El cuerpo de la función se reduciría a una sola línea que recibe los dos argumentos de la función (arg1 y arg2):<br />
<em>sort(seq(min(arg1),max(arg1),length.out=(arg2+1)))</em></p>
<p>El uso de esta función es muy sencillo:</p>
<pre class="brush: sql; title: ; notranslate">SELECT r_equal( array_accum(t1996t1), 5 ) FROM ine.poblacion_activa;</pre>
<p>Nos devolverá el siguiente array:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="576" valign="top">{36.3,465.18,894.06,1322.94,1751.82,2180.7}</td>
</tr>
</tbody>
</table>
<p>Para aquellos más versados en PLPg/SQL habrán advertido que realizar la función en este lenguaje requiere de algunas líneas más de código, que pueden ser bastantes más si queremos utilizar otros métodos, como el de cuantiles, que reproducimos a continuación.</p>
<pre class="brush: sql; title: ; notranslate">
CREATE OR REPLACE FUNCTION r_quantile(double precision[], integer)
RETURNS double precision[] AS
$BODY$
quantile(arg1,probs = seq(0, 1, 1/arg2))
$BODY$
LANGUAGE 'plr' VOLATILE STRICT
COST 100;
</pre>
<p>Ejemplo de uso para 5 intervalos de clase:</p>
<pre class="brush: sql; title: ; notranslate">
SELECT r_quantile(array_accum(t1996t1),5) FROM ine.poblacion_activa;</pre>
<p>Devuelve:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="576" valign="top">{36.3,104.7,174.2,251.3,409.7,2180.7}</td>
</tr>
</tbody>
</table>
<p>Ahora que tenemos implementado un método para calcular los intervalos de clase ya estamos en condiciones de desarrollar un auténtico motor de cartografía temática (corológica) en un ambiente web que combine la capacidad de cálculo de PL/R con la semiología cartográfica implementada en PHPcolorBrewer que sea capaz de &#8220;pintar&#8221; geometrias de una tabla espacial de PostGIS. El resultado de esta coctelera explosiva lo podeis ver en las siguientes demostraciones on-line:</p>
<p><a name="demos"><strong>EJEMPLOS</strong></a></p>
<p><strong>Test 1: <a href="/demos/j3m/plr/test1.php">Distribución de la población activa por provincias (valores en miles de personas)</a></strong><br />
Este sencillo ejemplo nos permite ver las posibilidades de integración de varias piezas de software (PostGIS, PL/R. PHP MapScripts y PHPcolorBrewer). Los cálculos de los intervalos de clase utilizan el método &#8220;Kmeans&#8221;, y el usuario tiene la posibilidad de cambiar la paleta de colores y el nº de clases, así como el año que desea consultar.</p>
<p><strong>Test 2: <a href="/demos/j3m/plr/test2.php">Distribución de la tasa de ocupación/desempleo por Comunidades Autónomas(valores en miles de personas)</a></strong><br />
Similar al anterior, pero aplicado a CC.AA. Ofrece la posibilidad de múltiples consultas (número de ocupados/desempleados diferenciando hombre, mujeres y total)</p>
<p><strong>Test 3: <a href="/demos/j3m/plr/test3.php">Distribución de la población activa por provincias (valores en miles de personas) según diferentes métodos de <em>clustering</em></a></strong><br />
Este ejemplo es similar al primero, pero hemos añadido la posibilidad de que el usuario selecciones el método de cálculo de intervalos de clase desea. Es sin duda, un buen ejemplo de la potencia que tiene PL/R al permitirnos elegir hasta 8 métodos diferentes:</p>
<ul>
<li><a href="/demos/j3m/plr/test3.php?paletas=YlOrRd&amp;numInt=5&amp;field=t2000t1&amp;method=quantile">quantile</a></li>
<li><a href="/demos/j3m/plr/test3.php?paletas=YlOrRd&amp;numInt=5&amp;field=t2000t1&amp;method=equal">equal</a></li>
<li><a href="/demos/j3m/plr/test3.php?paletas=YlOrRd&amp;numInt=5&amp;field=t2000t1&amp;method=kmeans">kmeans</a></li>
<li><a href="/demos/j3m/plr/test3.php?paletas=YlOrRd&amp;numInt=5&amp;field=t2000t1&amp;method=hclust.complete">hclust.complete</a></li>
<li><a href="/demos/j3m/plr/test3.php?paletas=YlOrRd&amp;numInt=5&amp;field=t2000t1&amp;method=hclust.single">hclust.single</a></li>
<li><a href="/demos/j3m/plr/test3.php?paletas=YlOrRd&amp;numInt=5&amp;field=t2000t1&amp;method=bclust">bclust</a></li>
<li><a href="/demos/j3m/plr/test3.php?paletas=YlOrRd&amp;numInt=5&amp;field=t2000t1&amp;method=fisher">fisher</a></li>
<li><a href="/demos/j3m/plr/test3.php?paletas=YlOrRd&amp;numInt=5&amp;field=t2000t1&amp;method=jenks">jenks</a></li>
</ul>
<p><strong>Test 4: <a href="/demos/j3m/plr/test4.php">Varios mapas temáticos en una sóla página con todos los métodos anteriores</a></strong><br />
El objeto de este ejemplo es demostrar de una sóla vez como se representa un mismo fenómeno desde diferentes métodos de clustering, para ver cual es el que mejor se adapta a nuestras necesidades.</p>
<p><strong>Test 5: <a href="/demos/j3m/plr/test5.php">Mapa temático municipal sensible con HTML dinámico</a></strong><br />
Se trata del ejemplo más completo de todos, que nos permite seleccionar una provincia y ver la distribución de la población (total, hombres o mujeres) por municipio. También permite seleccionar todos los métodos indicados, así como la paleta de colores y nº de intervalos.</p>
<p><strong>Test 6: <a href="/demos/j3m/plr/test6.php">Todas las paletas PHPcolorBrewer aplicadas a un mapa temático</a></strong><br />
El objetivo de este ejemplo es demostrar en una sóla página como un mismo fenómeno es representado con todas las paleta de PHPcolorBrewer, para que el usuario seleccione la que más le convenga.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2010/02/04/cartografia-tematica-ii-calculo-de-intervalos-de-clase-con-plr/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Integración de R en PostgreSQL. Mi primera función en pl/R.</title>
		<link>http://www.gisandchips.org/2009/09/24/integracion-de-r-en-postgresql-mi-primera-funcion-en-plr/</link>
		<comments>http://www.gisandchips.org/2009/09/24/integracion-de-r-en-postgresql-mi-primera-funcion-en-plr/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 08:49:58 +0000</pubDate>
		<dc:creator>benizar</dc:creator>
				<category><![CDATA[Análisis]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[pl/R]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[R]]></category>

		<guid isPermaLink="false">http://www.gisandchips.org/?p=165</guid>
		<description><![CDATA[En primer lugar, y para que ninguno de vosotros tenga impresión que no voy a hablar nunca de GIS, me gustaría tranquilizaros, y recordaros que en próximos artículos, yo o a quien le apetezca participar en este hilo, pasaremos a comentar usos de todo esto que estamos viendo orientado al tratamiento de la información espacial. [...]]]></description>
			<content:encoded><![CDATA[<p>En primer lugar, y para que ninguno de vosotros tenga impresión que no voy a hablar nunca de GIS, me gustaría tranquilizaros, y recordaros que en próximos artículos, yo o a quien le apetezca participar en este hilo, pasaremos a comentar usos de todo esto que estamos viendo orientado al tratamiento de la información espacial. Si hay alguien que quiera compartir sus experiencias con temas de R será bien recibido.</p>
<p>Este segundo artículo sobre tecnologías útiles para explotar toda la potencia de R se centra en el uso de R desde el PostgreSQL.</p>
<p>Como todos sabéis, tradicionalmente los Sistemas Gestores de Bases de Datos (SGBD), como PostgreSQL, Oracle, MySQL o Access han sido diseñados para guardar y gestionar gran cantidad de datos, por ello las posibilidades de análisis y salidas gráficas se han delegado mayormente en otros softwares como hojas de cálculo, paquetes estadísticos como SPSS, R o en nuestro caso en softwares SIG&#8230; pero eso se acabó  <img src='http://www.gisandchips.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />   .</p>
<p>pl/R es un lenguaje de programación procedural que permite contar con toda la potencia de cálculo y salidas gráficas del paquete estadístico R, así como de su lenguaje de programación desde dentro de funciones de PostgreSQL.</p>
<p><span id="more-165"></span></p>
<p>Los <span style="text-decoration: underline">requisitos básicos</span> para comenzar a trabajar con pl/R son, como no, tener instalado PostgreSQL (he trabajado sin demasiados problemas con las versiones 8.2 y 8.3), tener pl/R instalado, y crear una base de datos en PostgreSQL donde añadimos el nuevo lenguaje procedural.</p>
<p>Todo lo que necesitamos para iniciarnos lo podemos encontrar en la página WEB del creador de pl/R, <strong>Joe Conway</strong> (<a href="http://www.joeconway.com/plr/">http://www.joeconway.com/plr/</a> ), donde nos descargaremos los ficheros para la instalación tanto para Windows como para Linux. También hay documentación para dar los primeros pasos y unos cuantos más. Esta presentación os ayudará bastante (<a href="http://www.joeconway.com/oscon-pres-2003-1.pdf">http://www.joeconway.com/oscon-pres-2003-1.pdf</a> ). Os recomiendo leer todo lo que podáis, incluso su Curriculum que está en la página principal no tiene desperdicio.</p>
<p>Hay mucha documentación en Internet y ejemplos de funciones básicas. Nosotros para trabajar con algo que ya conocemos, volveremos a utilizar la función hist() de R para obtener el histograma de cualquier campo numérico que podamos tener en una tabla de nuestra base de datos.</p>
<p>Cualquiera que haya trabajado bien con R, bien con funciones de PostgreSQL en general encontrará rápidamente los primeros problemas o desventajas, si es que se pueden llamar así, de usar pl/R. En cualquiera de los dos casos, normalmente tendremos que aprender a usar una nueva herramienta (PostgreSQL o R), lo cual es un nuevo mundo. Depurar las funciones de pl/R puede ser engorroso si se hace directamente, y normalmente los procesos serán más lentos, proporcionalmente, que si trabajásemos solamente en uno de los dos lados del espejo.  Pero ahora os diré las ventajas que puedo destacar más rápidamente:</p>
<ul>
<li>Podemos ejecutar nuestras nuevas funciones mediante una      sencilla expresión de SQL,</li>
<li>las funciones estarán siempre junto con los datos      (acabando con la importación-exportación),</li>
<li>tenemos la posibilidad de usar las funciones desde PHP      y</li>
<li>un potente SGBD se encargará de gestionar el manejo de      los datos, lo cual es muy bueno cuando se trabaja con grandes volúmenes de      información.</li>
</ul>
<p>Hay más ventajas, pero creo que para empezar no está nada mal.</p>
<h3>Mi primera función en pl/R</h3>
<p>Una vez lo tenemos todo instalado, os recomiendo empezar probando que todo funciona bien desde el GUI de R, ya que desde pl/R nos será más complicada la depuración.</p>
<p>La función que paso a detallar está pensada para usarla en local y que la probéis con vuestros propios datos (numéricos; si no lo son veréis un mensaje de error). Se trata de crear un histograma y guardarlo como imagen.</p>
<p>Como os podéis dar cuenta parece una función de pl/pgSQL solo que cambiamos el lenguaje al final y metemos directamente código de R entre $BODYs o comillas simples, aunque resulta más práctico el $ por si dentro de la función necesitamos usar comillas de dos tipos.</p>
<p>Los comentarios de la función pueden ir con # igual que en R.</p>
<p>A continuación tenemos el código para crear la nueva función:</p>
<pre class="brush: sql; title: ; notranslate">

CREATE OR REPLACE FUNCTION _plr_hist(text, text)
RETURNS text AS
$BODY$
select = 'select '
campo = arg1
from = ' from '
tabla = arg2
selection = paste(select, campo, from, tabla, sep='');

## Ejecutamos la consulta y la almacenamos en el objeto &quot;sql&quot;;
sql &lt;- pg.spi.exec (selection);

## Lo que obtengamos a partir de aquí se imprimirá en un pdf...
dir='c:/temp/';
nam= arg1;
ext='.png';
newfile=paste(dir,nam,ext, sep='')
png(newfile);

hist(sql[,1], xlab = campo, ylab='frecuencias', main= campo, col='blue', ylim=c(0,20));

## Hasta aquí
dev.off();

## Si trabajamos en linux querremos hacer algo como lo siguiente
## para asignar privilegios de lectura a todos los usuarios de linux
##sys1='chmod go+r'
##sys2=paste(sys1, '', newfile)
##system(sys2)

## Esto devuelve un mensaje al terminar la función
print1='¡¡¡Ya está!!!, ¡¡¡mira que gráfico más chulo en'
print2=paste(print1, '', newfile, sep='')
print (print2);

$BODY$
LANGUAGE 'plr' VOLATILE
</pre>
<p>Dentro de la función hay que destacar el empleo de pg.spi.exec(),  para uso de los desarrolladores de PostgreSQL, que ejecuta una expresión dada.</p>
<p>Una vez creada nuestra función la podremos ejecutar de un modo muy sencillo. Fijaos que bueno que es esto  <img src='http://www.gisandchips.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />    :</p>
<pre class="brush: sql; title: ; notranslate">

select _plr_hist('un campo numérico', 'tabla');
</pre>
<p>Y obtenemos nuestra gráfica en la carpeta especificada.</p>
<h3>Algunos comentarios sobre todo esto:</h3>
<p>Viéndolo ya funcionar parece que nada “malo” pueda pasarnos. A este respecto, uno de los aspectos que más problemas me creó en su día es lo relacionado con los derechos del usuario Postgres en el SO, tanto en Linux como en Windows. La solución en linux viene dada y comentada en el código de más arriba. Con “chmod go+r” damos derechos de lectura a todos los usuarios. Lo que no me imaginaba nunca es que en Windows también iba a tener problemas. Resulta que el usuario que ejecuta el postmaster de Postgresql es “postgres”, que no dispone de derechos de escritura (no se si hay otros problemas) en “c:\”. Cuando se trata de crear una salida gráfica a c:\, el interprete de pl/R indica que no se puede iniciar el device(). Esto me llevó algún dolor de cabeza pues en Windows suelo hacer todas mis primeras pruebas directamente en c:\. En el ejemplo de antes trabajamos en un directorio creado a propósito. Sobre esto último podemos consultar en <a href="http://pgfoundry.org/pipermail/plr-general/2009-June/000264.html">http://pgfoundry.org/pipermail/plr-general/2009-June/000264.html</a> .</p>
<h3>Referencias:</h3>
<p>Solamente recordaros lo esencial de la página de Joe Conway (<a href="http://www.joeconway.com/plr/">http://www.joeconway.com/plr/</a> ). También os recomiendo entrar en <a href="http://www.bostongis.com/">http://www.bostongis.com/</a> donde hay un hilo de 3 artículos explicando distintos temas relacionados con pl/R. El primero es una introducción bastante detallada, el segundo es trata la creación de polígonos de Voronoi en PostgreSQL usando PostGIS y pl/R (muy recomendable, y avanzado), y el último es un ejemplo de uso de RGDAL.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>Si quereis contactar podeis enviarme un email (asunto: gisandchips):</p>
<p>Benito M. Zaragozí</p>
<p>benito.zaragozi@ua.es</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gisandchips.org/2009/09/24/integracion-de-r-en-postgresql-mi-primera-funcion-en-plr/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

