<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Graphicmethod Studio</title>
    <description>The latest articles on DEV Community by Graphicmethod Studio (@graphicmethod).</description>
    <link>https://dev.to/graphicmethod</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1160674%2Fa2cccb51-95cb-45dd-b965-8f64d195dd50.jpg</url>
      <title>DEV Community: Graphicmethod Studio</title>
      <link>https://dev.to/graphicmethod</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/graphicmethod"/>
    <language>en</language>
    <item>
      <title>Como llegar desde un dataset netCDF a una representación en RAWgraphs.</title>
      <dc:creator>Graphicmethod Studio</dc:creator>
      <pubDate>Tue, 24 Oct 2023 00:06:30 +0000</pubDate>
      <link>https://dev.to/graphicmethod/como-llegar-desde-un-dataset-netcdf-a-una-representacion-en-rawgraphs-2d49</link>
      <guid>https://dev.to/graphicmethod/como-llegar-desde-un-dataset-netcdf-a-una-representacion-en-rawgraphs-2d49</guid>
      <description>&lt;p&gt;Hace unas semanas desde la ESA se lanzó el concurso “&lt;a href="https://climate.esa.int/en/littlepicturescompetition/"&gt;little pictures&lt;/a&gt;” Se pide a los participantes transformar datos derivados de observaciones satelitales a pequeñas visualizaciones que llamen la atención sobre el cambio climático.&lt;/p&gt;

&lt;p&gt;Ofrecen &lt;a href="https://github.com/littlepictures/datasets"&gt;algunos datasets ya preparados&lt;/a&gt; pero quise aprovechar para para investigar un poco los datasets de “&lt;strong&gt;&lt;a href="https://cds.climate.copernicus.eu/#!/home"&gt;Climate Data Store&lt;/a&gt;”&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Hay &lt;a href="https://cds.climate.copernicus.eu/cdsapp#!/search?type=dataset"&gt;montones de datasets de muchos tipos&lt;/a&gt; Vienen en un formato llamado netCDF que nunca habíamos trabajado, ¡otro motivo más para dedicar un rato a “little pictures”!  Sin ser muy experto ni en R ni en netCDF, voy a tratar compartir lo que he aprendido.&lt;/p&gt;

&lt;p&gt;Lo primero que llama la atención de los archivos netCDF es que pesan bastante. No es un excel de unos pocos megas sino que es fácil que ocupen 100 mb por archivo. ¿Por qué?&lt;/p&gt;

&lt;p&gt;Vamos a ver un ejemplo de una representación de uno de estos archivos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8VoEJHTS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/alewwo23sl7o5mttyfb0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8VoEJHTS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/alewwo23sl7o5mttyfb0.png" alt="Representación NetCDF en panoply" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para abrirlo he usado &lt;a href="https://www.giss.nasa.gov/tools/panoply/"&gt;Panoply&lt;/a&gt; que es fácil aunque muy básico. QGIS también lo abre. &lt;br&gt;
Observamos una gráfica con latitud-longitud en el que con cierta resolución (décima de grado, centésima de grado…) se representa un valor.&lt;/p&gt;

&lt;p&gt;Por tanto vamos a tener ya un montón de puntos ahí. Pero es que además, lo habitual es tener no solo una “foto fija” sino también el valor de la evolución a lo largo de un periodo de tiempo. Y no solo de una variable sino incluso de varias. Ya vamos viendo de donde salen los 100 megas del archivo.&lt;/p&gt;

&lt;p&gt;Estos archivos además  son “autodescriptivos” es decir llevan incorporada la metadata sobre su contenido.&lt;/p&gt;

&lt;p&gt;Las captura y el resto del artículo los voy a hacer con este dataset &lt;a href="https://cds.climate.copernicus.eu/cdsapp#!/software/app-health-aedes-albopictus-projections?tab=app"&gt;Sobre la duración de la actividad del mosquito tigre en europa&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Simplificando
&lt;/h2&gt;

&lt;p&gt;Si hacemos visualizaciones web no nos gusta obligar a la gente a descargar 100 megas de datos. Sobre todo si lo que nos interesa es responder a una pregunta simple, por ejemplo: ¿Cual va a ser la evolución del mosquito tigre en una ciudad?&lt;/p&gt;

&lt;p&gt;En este caso voy a querer pasar de este formato de datos donde tengo un grid de puntos y un valor (llamemosle un formato 3D) + el tiempo (4D)A un formato 2D donde solo quiero la evolución temporal del valor dado un lugar en el mapa.&lt;/p&gt;
&lt;h3&gt;
  
  
  Código
&lt;/h3&gt;

&lt;p&gt;Desde el proyecto de &lt;a href="https://cds.climate.copernicus.eu/cdsapp#!/home"&gt;Climate Data Store&lt;/a&gt; ofrecen muchos ejemplos de código en python y aplicaciones para copiar. Pero para estas cosas me manejo un poco mejor en R. Encontré estos recursos que os recomiendo leer para entender mejor lo de los archivos  netCDF&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://towardsdatascience.com/how-to-crack-open-netcdf-files-in-r-and-extract-data-as-time-series-24107b70dcd"&gt;https://towardsdatascience.com/how-to-crack-open-netcdf-files-in-r-and-extract-data-as-time-series-24107b70dcd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rpubs.com/boyerag/297592"&gt;https://rpubs.com/boyerag/297592&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trabajando con el paquete &lt;a href="https://cran.r-project.org/web/packages/ncdf4/index.html"&gt;NETCDF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Antes de todo vamos a definir las ciudades que nos interesan, por ejemplo estas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;POIS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s1"&gt;'Berlin'&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;13.404954&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;52.520008&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#long lat&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s1"&gt;'Budapest'&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;19.040236&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;47.497913&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s1"&gt;'Paris'&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2.354478&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;48.860506&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como decía arriba, el propio archivo contiene su metadata. Así que en este caso si lo abrimos nos dice su contenido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;nc_file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nc_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"mosquito_seas_rcp85_mean_v1.0.nc"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# change 85 for 45 for other experiment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nc_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# saca entre otras cosas:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;excluding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dimension&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;        
    &lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;season_length&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Contiguous&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;              
    &lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="n"&gt;FillValue&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="w"&gt;            
    &lt;/span&gt;&lt;span class="n"&gt;units&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;            
    &lt;/span&gt;&lt;span class="n"&gt;long_name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ensemble&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;members&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;average&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VBD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;season_length&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;climate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;under&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rcp85&lt;/span&gt;&lt;span class="w"&gt;            
    &lt;/span&gt;&lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;....&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dimensions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt;        
&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;425&lt;/span&gt;&lt;span class="w"&gt;             
        &lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="n"&gt;FillValue&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="w"&gt;            
        &lt;/span&gt;&lt;span class="n"&gt;units&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;degrees_north&lt;/span&gt;&lt;span class="w"&gt;            
        &lt;/span&gt;&lt;span class="n"&gt;standard_name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="w"&gt;        
&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;599&lt;/span&gt;&lt;span class="w"&gt;             
        &lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="n"&gt;FillValue&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="w"&gt;            
      &lt;/span&gt;&lt;span class="n"&gt;units&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;degrees_east&lt;/span&gt;&lt;span class="w"&gt;            
        &lt;/span&gt;&lt;span class="n"&gt;standard_name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="w"&gt;        
&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt;             
        &lt;/span&gt;&lt;span class="n"&gt;standard_name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt;            
        &lt;/span&gt;&lt;span class="n"&gt;units&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;since&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1986-01-01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;&lt;span class="w"&gt;            
        &lt;/span&gt;&lt;span class="n"&gt;calendar&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;proleptic_gregorian&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Donde vemos que nos dice las dimensiones con sus unidades. Ojo que aquí no hay estándar. Por ejemplo, las unidades de tiempo no tienen por qué ser UNIX time, aquí dice que son días transcurridos desde 1 de Enero de 1986. &lt;/p&gt;

&lt;p&gt;En los artículos de arriba vienen mejor explicadas las formas de acceder al contenido del archivo usando ncvar_get y ncatt_get&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="c1"&gt;#ncvar_get nos devuelve la estructura de datos de una de las variables&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ncvar_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nc_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# days after first datum&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;##&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;365&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;730&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1461&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1826&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vemos que tenemos el array de tiempo con 100 valores (100 años) desde 0 y sumando 365 (o 366) días&lt;/p&gt;

&lt;p&gt;si hacemos :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;seasonLength_array&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ncvar_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nc_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"season_length"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahí vamos a tener un montón de datos. ¡¡TODOS los valores de season_length!! Así que vamos a ir simplificando. Podemos extraer un fotograma fijo de esos datos eligiendo un momento en el tiempo. Por ejemplo el año 1 o el año 20&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;seasonLength_slice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seasonLength_array&lt;/span&gt;&lt;span class="p"&gt;[,,&lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seasonLength_slice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;brewer.pal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"YlOrRd"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al fijar un año lo que tenemos es el conjunto de todos los valores para ese año en función de (Lat, Lon)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gfG9xIh0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nhvf2fd4l6wjqtgkae1m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gfG9xIh0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nhvf2fd4l6wjqtgkae1m.png" alt="Diagrama de los datos temporales de un archivo netCDF" width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pero lo que queremos hacer no es fijar el año sino la longitud y latitud. Para ello necesitamos encontrar el indice de las coordenadas más cercanas a las coordenadas de cada ciudad.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;seasonLength_df&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data.frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;character&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;seasonLength_byTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;names&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;POIS&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c1"&gt;# get the lat and lon for the current city&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;sample_lat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;POIS&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;]][&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;sample_lon&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;POIS&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;]][&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="c1"&gt;# find the closest lat/lon index in the grid&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;lon_index&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;which.min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_lon&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;lat_index&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;which.min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sample_lat&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="c1"&gt;# get the seasonLength_byTime for the current city&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;seasonLength_byTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seasonLength_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lon_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lat_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="c1"&gt;#Adjust the data to the dataframe format&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;seasonLength_df_city&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data.frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;rep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time_obs&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time_obs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"%Y"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;seasonLength_byTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;seasonLength_df&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rbind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seasonLength_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seasonLength_df_city&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1Zw-dtKW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w8kxcsn823fp1jkm1w8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Zw-dtKW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w8kxcsn823fp1jkm1w8m.png" alt="Tabla de datos" width="482" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El dataframe de resultados está ya listo para exportarse a CSV, y tenemos las tres ciudades con su nombre en la primera columna.&lt;/p&gt;

&lt;p&gt;Si representamos el valor de seasonLength_byTime en cada iteración, tenemos la evolución en una de las ciudades.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B8f6MYk9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gqjww5cc22m5v81ee3v6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B8f6MYk9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gqjww5cc22m5v81ee3v6.png" alt="Gráfica de evolución del dato en una ciudad determinada" width="800" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Por último indicar que esto es una forma un poco de andar por casa, seguramente sea más potente usar el package “Raster” &lt;a href="https://pjbartlein.github.io/REarthSysSci/raster_intro.html"&gt;https://pjbartlein.github.io/REarthSysSci/raster_intro.html&lt;/a&gt; Uno de los problemas que se me ocurre que pueden aparecer es que el dataset sea muy variable en la dimensión espacial. Es decir que una centésima de grado mas allá o mas acá oscile mucho el valor. En este caso habría que calcular una media de una región, algo que costaría más hacer con este método&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Siguientes pasos
&lt;/h2&gt;

&lt;p&gt;Para hacer un cartel estilo &lt;a href="https://climate.esa.int/en/little-pictures-gallery/"&gt;los de little pictures&lt;/a&gt; quedaría representar los datos con un objetivo comunicativo. Por ejemplo podríamos mirar a ver que pasa al  comparar el escenario RCP 4.5 y 8.5 y el año 0 ( 1985) &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Cuando los científicos pasan de “observaciones” a modelos de predicción utilizan distintos escenarios futuros llamados “trayectoria de concentración representativa” &lt;a href="https://es.wikipedia.org/wiki/Trayectorias_de_concentraci%C3%B3n_representativas"&gt;https://es.wikipedia.org/wiki/Trayectorias_de_concentración_representativas&lt;/a&gt; que se diferencian en cuantas emisiones de CO2 vamos a ser capaces de recortar en este siglo. Este dataset se ofrece para trayectorias 4.5 y 8.5&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Podemos generar dos CSVs cambiando el archivo de entrada y luego pegarlos a mano usando una hoja de cálculo (por aquí somos muy fans del  &lt;a href="https://vdt-labs.com/easy-csv-editor/"&gt;easy CSV editor&lt;/a&gt;)  y añadir una columna nueva para diferenciar el modelo de emisiones utilizado ( rcp85 o rcp45)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;experiment&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;rcp85&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Berlin&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1986&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;79.9151763916016&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;rcp85&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Berlin&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1987&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;79.9485092163086&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;rcp85&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Berlin&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1988&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;81.0975112915039&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;rcp85&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Berlin&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1989&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;80.5817642211914&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luego podemos ir &lt;a href="https://www.rawgraphs.io"&gt;RAWgraphs&lt;/a&gt; Importar el archivo CSV y echar un vistazo&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c8aCvs4i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xz0kupgqsde0quv7245u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c8aCvs4i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xz0kupgqsde0quv7245u.png" alt="Mapeo de datos en Raw Graphs" width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U4t8wwqb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ukswmge702b31ca1eoe9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U4t8wwqb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ukswmge702b31ca1eoe9.png" alt="Gráficas de líneas en Raw Graphs" width="800" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si lo comparamos con el mapa se aprecia como la duración de la estación del mosquito crece, sobre todo en países hacia el este, donde ahora es muy corta. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--utqJN3JO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bww7ah71auvsr6flu748.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--utqJN3JO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bww7ah71auvsr6flu748.gif" alt="Animación mosquito tigre" width="480" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tal y como lo veo, RAWgraphs no está diseñado para obtener una gráfica ya perfecta, sino más bien como una herramienta intermedia para generar visualizaciones básicas que puedan exportarse a SVG (y desde ahí trabajarlas en otro software, tipo Figma o Illustrator)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FRXJLOII--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/78n9ucgc0s5fyasjowf2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FRXJLOII--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/78n9ucgc0s5fyasjowf2.png" alt="Exportar a SVG en la interface de raw graphs" width="653" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A partir de aquí, ahora llegaría el momento  de hacer algo bonito con estas gráficas: darle una vuelta, pensar de qué manera los datos crean mas impacto, comunican mejor... o lo que sea que queramos conseguir. Ahí ya depende de cada uno.&lt;/p&gt;

</description>
      <category>netcdf</category>
      <category>r</category>
      <category>datascience</category>
      <category>datavisualization</category>
    </item>
    <item>
      <title>A Netlify build plugin to pull data from Seatable</title>
      <dc:creator>Graphicmethod Studio</dc:creator>
      <pubDate>Thu, 14 Sep 2023 00:12:37 +0000</pubDate>
      <link>https://dev.to/graphicmethod/a-netlify-build-plugin-to-pull-data-from-seatable-19o2</link>
      <guid>https://dev.to/graphicmethod/a-netlify-build-plugin-to-pull-data-from-seatable-19o2</guid>
      <description>&lt;p&gt;It is a common scenario for us to build a data visualization site with small datasets in the form of CSV/JSON files. But then the client wants to have a database interface to update the data from time to time. In this case, we think that using a backend with an API... is a waste of resources when all you need is just a CSV/JSON.&lt;/p&gt;

&lt;p&gt;So the solution we found is to use &lt;a href="http://seatable.io/"&gt;SeaTable&lt;/a&gt;: as a headless CMS. SeaTable is a kind of Airtable but European, GDPR compliant, and with many interesting features.&lt;/p&gt;

&lt;p&gt;But it is not really a database intended to be used as a backend: We don’t want to connect each visitor's browser directly with the database.&lt;br&gt;
So we just needed a way to download the data from the database and save it as a JSON file. Then we can use this JSON file in the build process to generate a static site with NUXT or NEXT for instance.&lt;/p&gt;

&lt;p&gt;Since we use Netlify as our primary hosting solution, we created a Netlify build plugin that downloads the data from SeaTable before each build.&lt;/p&gt;

&lt;p&gt;This plugin is available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/thegraphicmethod/netlify-plugin-seatable"&gt;https://github.com/thegraphicmethod/netlify-plugin-seatable&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is not officially supported by SeaTable. It is a plugin we created for our own needs and we are sharing it in case it can be useful for someone else. But please, do some testing before moving to production, we need more users to be sure that it works in all cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to use it&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;install the plugin with npm:&lt;br&gt;
&lt;code&gt;npm install -D netlify-plugin-seatable&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to your SeaTable admin panel and get the API key for the base you want to use. You can get the API Key for a Base in the advanced section of the base settings.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZwyyZ9TF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f825z3ls3sxug0pdtkjp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZwyyZ9TF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f825z3ls3sxug0pdtkjp.png" alt="Where to find the token" width="458" height="480"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In your application, add a netlify.toml file with the following content:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[plugins]]
package = "netlify-plugin-seatable"
# Plugin configuration
[plugins.inputs]
SEATABLE_TABLE_NAME = "Table1,Table2"
DATA_FOLDER = "assets/data"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;SEATABLE_TABLE_NAME&lt;/strong&gt; could be a single table name or multiple table names separated by a comma (no spaces between names)&lt;br&gt;
For each table, a JSON file will be created in the DATA_FOLDER folder.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since the API token is a secret, it is not recommended to have it in your repository. So, in the Netlify app add the following environment variable:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;SEATABLE_APP_TOKEN (which is the token of the Seatable app)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;That’s it. Now each time you build your site the plugin will download the data from SeaTable BEFORE BUILDING and will save it in the specified folder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please note that the DATA_FOLDER must exist in the repository. The plugin will not create it.&lt;br&gt;
Also, note that the plugin will overwrite the JSON file if it already exists but it won't commit to the repository. It is only available during the build process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sJQXn8Zb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5zcmt9ulqnsjcbo2scg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sJQXn8Zb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5zcmt9ulqnsjcbo2scg2.png" alt="Logs from the plugin building stage" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feedback&lt;/strong&gt;&lt;br&gt;
This is our first Netlify plugin so any feedback is welcome. Let us know if you find it useful or if you have any suggestions to improve it.&lt;/p&gt;

</description>
      <category>netlify</category>
      <category>automation</category>
      <category>database</category>
    </item>
  </channel>
</rss>
