Reading and Tidying Barcelona Air Quality Data

Jose M Sallan 2025-07-27 52 min read

Through open data portals, governments and city councils provide data to citizens in a transparent and accesible format, so it can be reused for research, app development, and civic tech.

In this post, I will show how to retrieve data into R from an open data portal using the CKAN API technology, and structure it in tidy format with the tools of the tidyverse. Specifically, my aim is to retrieve Barcelona air quality data from the Open Data BCN portal.

I will be using the tidyverse for data reading, handling and plotting, janitor to clean column names and the ckanr package to interact with the CKAN API of the portal.

library(tidyverse)
library(janitor)
library(ckanr)

I need all the URLs of air quality data files. To get them, I set up the Open Data BCN portal with ckanr::ckanr_setup().

ckanr_setup(url = "https://opendata-ajuntament.barcelona.cat/data/")

The datasets available at a portal using CKAN are called packages. Let’s see the package list of the portal.

package_list(as = "table", limit = 1000)
##   [1] "20170706-districtes-barris"                                
##   [2] "accessibilitat-via-publica"                                
##   [3] "accidents_causa_conductor_gu_bcn"                          
##   [4] "accidents-causes-gu-bcn"                                   
##   [5] "accidents-gu-bcn"                                          
##   [6] "accidents-persones-gu-bcn"                                 
##   [7] "accidents-tipus-gu-bcn"                                    
##   [8] "accidents-vehicles-gu-bcn"                                 
##   [9] "accions-formatives-adrecades-al-personal"                  
##  [10] "acollida-animals"                                          
##  [11] "administracio-autonomica"                                  
##  [12] "administracio-estatal"                                     
##  [13] "administracio-municipal"                                   
##  [14] "afectacions-turistiques"                                   
##  [15] "afectacions-turistiques-a-espais-verds"                    
##  [16] "aforaments-descriptiu"                                     
##  [17] "aforaments-detall"                                         
##  [18] "aforament-tipus-equipament"                                
##  [19] "agenda-activitats-esportives"                              
##  [20] "agenda-cultural"                                           
##  [21] "agenda-diaria"                                             
##  [22] "agenda-publica-alcaldesa"                                  
##  [23] "agendes-publiques-comissionats"                            
##  [24] "agendes-publiques-regidors"                                
##  [25] "alcaldes-alcaldesses-bcn"                                  
##  [26] "allotjaments-altres"                                       
##  [27] "allotjaments-hotels"                                       
##  [28] "allotjaments-pensions"                                     
##  [29] "ampliacio-voreres-bici-bcn"                                
##  [30] "aparcaments-bcn"                                           
##  [31] "aparcaments-servei-bicis"                                  
##  [32] "aparcaments-sota-superficie"                               
##  [33] "arbrat-parcs"                                              
##  [34] "arbrat-viari"                                              
##  [35] "arbrat-zona"                                               
##  [36] "arbres-interes-local"                                      
##  [37] "arees-esbarjo-gossos-bcn"                                  
##  [38] "atles-biodiversitat-arbrat-especies"                       
##  [39] "atles-biodiversitat-arbrat-geometries"                     
##  [40] "atles-biodiversitat-arbrat-rel-geometria-especie"          
##  [41] "atles-biodiversitat-flora-especies"                        
##  [42] "atles-biodiversitat-flora-geometries"                      
##  [43] "atles-biodiversitat-flora-rel-geometria-especie"           
##  [44] "atles-renda-bruta-per-llar"                                
##  [45] "atles-renda-bruta-per-persona"                             
##  [46] "atles-renda-index-gini"                                    
##  [47] "atles-renda-mediana"                                       
##  [48] "atles-renda-mitjana"                                       
##  [49] "atles-renda-p80-p20-distribucio"                           
##  [50] "autenticacions-punts-recarrega-electric"                   
##  [51] "aut-terrasses-excep-decret-21-5"                           
##  [52] "bancs-del-temps-bcn"                                       
##  [53] "barcelona-activa-projectes"                                
##  [54] "benzineres"                                                
##  [55] "biblioteca_arus_bcnroc"                                    
##  [56] "bicicletes"                                                
##  [57] "bicing"                                                    
##  [58] "calendari-festes-laborals"                                 
##  [59] "campanyes-publicitat-institucional"                        
##  [60] "capacitat-mapa-estrategic-soroll"                          
##  [61] "carrecs-electes-comissionats-i-gerents"                    
##  [62] "carrerer"                                                  
##  [63] "carrers-30-bcn"                                            
##  [64] "carrers-pacificats-bici-bcn"                               
##  [65] "carrers-plataforma-unica-bcn"                              
##  [66] "carrers-vianants-bcn"                                      
##  [67] "carril-bici"                                               
##  [68] "carrils-bici-en-construccio"                               
##  [69] "carrils-bici-municipis"                                    
##  [70] "carta-arqueologica-barcelona"                              
##  [71] "cataleg-bases-ajuts-subvencions-bcnroc"                    
##  [72] "cataleg-bases-us-espai-public-bcnroc"                      
##  [73] "cataleg-bcnroc"                                            
##  [74] "cataleg-cartes-de-serveis-i-politiques-de-qualitat-bcnroc" 
##  [75] "cataleg-cartobcn"                                          
##  [76] "cataleg-circulars-bcnroc"                                  
##  [77] "cataleg-comptes-bcnroc"                                    
##  [78] "cataleg-costos-bcnroc"                                     
##  [79] "cataleg-declaracions-institucionals-bcnroc"                
##  [80] "cataleg-decrets-alcaldia-bcnroc"                           
##  [81] "cataleg-dictamens-bcnroc"                                  
##  [82] "cataleg-directrius-bcnroc"                                 
##  [83] "cataleg-documents-alcaldes-bcnroc"                         
##  [84] "cataleg-documents-tecnics-bcnroc"                          
##  [85] "cataleg-dossiers-notes-premsa-bcnroc"                      
##  [86] "cataleg-enquestes-bcnroc"                                  
##  [87] "cataleg-estatuts-bcnroc"                                   
##  [88] "cataleg-fotografies-art-public-bcnroc"                     
##  [89] "cataleg-fotografies-barcelona-general-bcnroc"              
##  [90] "cataleg-fotografies-cementiris-bcnroc"                     
##  [91] "cataleg-fotografies-edificis-bcnroc"                       
##  [92] "cataleg-fotografies-elements-urbans-bcnroc"                
##  [93] "cataleg-fotografies-projectes-urbans-bcnroc"               
##  [94] "cataleg_fotografies_temes_bcnroc"                          
##  [95] "cataleg-havana-bcnroc"                                     
##  [96] "cataleg-informes-avaluacio-bcnroc"                         
##  [97] "cataleg-informes-diversos-bcnroc"                          
##  [98] "cataleg-informes-organs-govern-bcnroc"                     
##  [99] "cataleg-instruccions-bcnroc"                               
## [100] "cataleg-laudes-bcnroc"                                     
## [101] "cataleg-memories-bcnroc"                                   
## [102] "cataleg-mesures-govern-bcnroc"                             
## [103] "cataleg-opendata"                                          
## [104] "cataleg-ordenances-fiscals-preus-bcnroc"                   
## [105] "cataleg-ordenances-municipals-bcnroc"                      
## [106] "cataleg-plans-especials-bcnroc"                            
## [107] "cataleg-plans-estrategics-bcnroc"                          
## [108] "cataleg-premis-bcnroc"                                     
## [109] "cataleg-pressupostos-bcnroc"                               
## [110] "cataleg-protocols-bcnroc"                                  
## [111] "cataleg-publicacions-bcnroc"                               
## [112] "cataleg-reglaments-bcnroc"                                 
## [113] "cataleg-rei-bcnroc"                                        
## [114] "cataleg-revistes-bcnroc"                                   
## [115] "cementiris"                                                
## [116] "cens-activitats-economiques-class-bcn"                     
## [117] "cens-animals-companyia"                                    
## [118] "cens-locals-planta-baixa-act-economica"                    
## [119] "centres-civics-activitatsdifusio"                          
## [120] "centres-civics-entitats"                                   
## [121] "centres-civics-formacio"                                   
## [122] "centres-civics-metres-quadrats"                            
## [123] "cinemes-dades-globals"                                     
## [124] "cobertura-vegetal-ndvi"                                    
## [125] "cohesio-social"                                            
## [126] "colors-aparcaments-superficie"                             
## [127] "comissaries-policia"                                       
## [128] "compatibilitats"                                           
## [129] "compliment-objectius-estabilitat"                          
## [130] "comportament-energetic-edificis"                           
## [131] "confort-termic"                                            
## [132] "consolats-bcn"                                             
## [133] "consum-aigua"                                              
## [134] "consum-electricitat-bcn"                                   
## [135] "contaminacio-atmosferica"                                  
## [136] "contaminants-estacions-mesura-qualitat-aire"               
## [137] "contractes-menors"                                         
## [138] "contractes-menors-a-generica"                              
## [139] "corredors-bici-bcn"                                        
## [140] "culturailleure-bibliotequesimuseus"                        
## [141] "culturailleure-cinemesteatresauditoris"                    
## [142] "culturailleure-espaisinfantils"                            
## [143] "culturailleure-espaismusicacopes"                          
## [144] "culturailleure-espaisparticipaciociutadana"                
## [145] "culturailleure-parcsjardins"                               
## [146] "dades-arts-esceniques"                                     
## [147] "dades-arxius"                                              
## [148] "dades-ateneus"                                             
## [149] "dades-festes-ciutat"                                       
## [150] "dades-festival-grec"                                       
## [151] "dades-festivals"                                           
## [152] "dades-globals-cultura"                                     
## [153] "dades-grans-auditoris"                                     
## [154] "dades-merce"                                               
## [155] "dades-museus-exposicions"                                  
## [156] "dades-projectes-fabriques-creacio"                         
## [157] "dades-sales-musica-viu-agrup-dimensions"                   
## [158] "dades-sindicals"                                           
## [159] "dades-xarxa-biblioteques-catalunya"                        
## [160] "deficit-proximitat-espai-verd"                             
## [161] "densitat-activitats"                                       
## [162] "densitat-huts"                                             
## [163] "denuncies_sancions_transit_bcn_codis"                      
## [164] "denuncies_sancions_transit_bcn_conceptes_annex"            
## [165] "denuncies_sancions_transit_bcn_detall"                     
## [166] "denuncies_sancions_transit_bcn_tip_vehicle"                
## [167] "dutxes-platges"                                            
## [168] "ebsib-bcn-enquesta-benestar-subjectiu-infancia"            
## [169] "edificis-amics-de-la-bici-barcelona"                       
## [170] "educacio-ensenyament-infantil"                             
## [171] "educacio-ensenyament-no-reglat"                            
## [172] "educacio-ensenyament-reglat"                               
## [173] "enquesta-escletxa-digital"                                 
## [174] "entitas-pacte-mobilitat"                                   
## [175] "entitats"                                                  
## [176] "entitats-municipals"                                       
## [177] "equipament-administracio"                                  
## [178] "equipament-animals-i-plantes"                              
## [179] "equipament-associacions"                                   
## [180] "equipament-cementiris-i-serveis-relacionats"               
## [181] "equipament-centres-d-informacio"                           
## [182] "equipament-companyies-de-serveis"                          
## [183] "equipament-cultura-i-lleure"                               
## [184] "equipament-educacio"                                       
## [185] "equipament-esports"                                        
## [186] "equipament-medi-ambient-i-serveis-relacionats"             
## [187] "equipament-mercats-i-centres-comercials"                   
## [188] "equipament-mitjans-de-comunicacio-i-serveis-relacionats"   
## [189] "equipament-restaurants"                                    
## [190] "equipament-sanitat"                                        
## [191] "equipaments-culturals-icub"                                
## [192] "equipament-serveis-religiosos"                             
## [193] "equipament-serveis-socials"                                
## [194] "equipaments-i-parcs-refugi"                                
## [195] "equipaments-relacionats-amb-transports"                    
## [196] "equipament-transports-i-serveis-relacionats"               
## [197] "escales-mecaniques"                                        
## [198] "esm-bcn-evo"                                               
## [199] "espais-creacio-activitats-difusio"                         
## [200] "espais-creacio-formacio-professionals"                     
## [201] "espais-creacio-metres-quadrats"                            
## [202] "espais-prioritaris-neteja-barcelona"                       
## [203] "espais-verds-publics"                                      
## [204] "esports-equip"                                             
## [205] "esports-individuals"                                       
## [206] "esports-instal-lacions-esportives"                         
## [207] "estacionaments-dum"                                        
## [208] "estacions-bus"                                             
## [209] "estacions-maritimes"                                       
## [210] "estat-estacions-bicing"                                    
## [211] "estat-ports-recarrega-electric"                            
## [212] "est-cadastre-carrecs-quota-cadastral"                      
## [213] "est-cadastre-carrecs-tipus-propietari"                     
## [214] "est-cadastre-carrecs-us"                                   
## [215] "est-cadastre-carrecs-valors-cadastrals"                    
## [216] "est-cadastre-edificacions-any-const"                       
## [217] "est-cadastre-edificacions-edat-mitjana"                    
## [218] "est-cadastre-edificacions-nombre-locals"                   
## [219] "est-cadastre-edificacions-superficie"                      
## [220] "est-cadastre-finques-regim-propietat"                      
## [221] "est-cadastre-finques-superficie"                           
## [222] "est-cadastre-habitatges-any-const"                         
## [223] "est-cadastre-habitatges-edat-mitjana"                      
## [224] "est-cadastre-habitatges-propietari"                        
## [225] "est-cadastre-habitatges-superficie"                        
## [226] "est-cadastre-habitatges-superficie-mitjana"                
## [227] "est-cadastre-habitatges-valor-cadastral"                   
## [228] "est-cadastre-locals-prop"                                  
## [229] "est-cadastre-locals-sup"                                   
## [230] "est-cadastre-locals-us-desti"                              
## [231] "est-cadastre-locals-valors-total-unitaris"                 
## [232] "est-demo-taxa-migracio-interna"                            
## [233] "est-densitat"                                              
## [234] "est-eleccions-autonomiques-seccio-censal"                  
## [235] "est-eleccions-europees-seccio-censal"                      
## [236] "est-eleccions-generals-seccio-censal"                      
## [237] "est-eleccions-locals-seccio-censal"                        
## [238] "est-social-discapacitats-grau"                             
## [239] "est-social-discapacitats-grups-edat"                       
## [240] "est-social-discapacitats-sexe"                             
## [241] "est-social-discapacitats-tipus"                            
## [242] "est-superficie"                                            
## [243] "est-vehicles-amb-distintiu"                                
## [244] "est-vehicles-antiguitat-menys-un-any"                      
## [245] "est-vehicles-antiguitat-motos"                             
## [246] "est-vehicles-antiguitat-tipus"                             
## [247] "est-vehicles-antiguitat-turismes"                          
## [248] "est-vehicles-cilindrada-motos"                             
## [249] "est_vehicles_evolucio_total"                               
## [250] "est_vehicles_index_motor"                                  
## [251] "est-vehicles-nacionalitat-propietari"                      
## [252] "est-vehicles-nacionalitat-propietari-motos"                
## [253] "est-vehicles-potencia-fiscal-turismes"                     
## [254] "est_vehicles_propulsio"                                    
## [255] "est_vehicles_servei"                                       
## [256] "est-vehicles-tipologia-parc-vehicles"                      
## [257] "est-vehicles-tipus-propietari"                             
## [258] "est-vehicles-tipus-propietari-motos"                       
## [259] "evolucio-despeses-corrents-per-politiques"                 
## [260] "evolucio-despeses-per-capitols"                            
## [261] "evolucio-despeses-per-capitols-i-articles"                 
## [262] "evolucio-despeses-per-unitats-organiques"                  
## [263] "evolucio-deute"                                            
## [264] "evolucio-ingressos-per-capitols"                           
## [265] "evolucio-ingressos-per-capitols-i-articles"                
## [266] "evolucio-resultat-ingressos-i-despeses"                    
## [267] "exclusio-residencial"                                      
## [268] "facanes-mapa-estrategic-soroll"                            
## [269] "factor-de-vulnerabilitat"                                  
## [270] "fitxer_entitats"                                           
## [271] "fitxes-ocupacionals"                                       
## [272] "fonts"                                                     
## [273] "fonts-ornamentals"                                         
## [274] "formacio-poblacio-insuficient"                             
## [275] "frase"                                                     
## [276] "funiculars"                                                
## [277] "galeries-comercials"                                       
## [278] "grans-centres-comercials"                                  
## [279] "grans-establiments"                                        
## [280] "gruamunicipalbcn-retirada-codis"                           
## [281] "gruamunicipalbcn-retirada-diposits"                        
## [282] "gruamunicipalbcn-retiradavehicles"                         
## [283] "h2mave-anualt1b"                                           
## [284] "h2mave-anualt2b"                                           
## [285] "h2mave-anualt3b"                                           
## [286] "h2mave-semestralt1b"                                       
## [287] "h2mave-semestralt2b"                                       
## [288] "h2mave-semestralt3b"                                       
## [289] "h2mave-totalt1b"                                           
## [290] "h2mave-totalt2b"                                           
## [291] "h2mave-totalt3b"                                           
## [292] "h2mave-totalt4b"                                           
## [293] "h2mave-totalt5b"                                           
## [294] "habitatges-2na-ma"                                         
## [295] "habitatges-us-turistic"                                    
## [296] "habit-fam-dest-habit-segons-any-const"                     
## [297] "habit-fam-sit-edif-dest-habit-segons-tip"                  
## [298] "habit-ppal-segons-any-const"                               
## [299] "habit-ppal-segons-estat-conserv-edif"                      
## [300] "habit-ppal-segons-instal1-calef"                           
## [301] "habit-ppal-segons-instal2-aigua"                           
## [302] "habit-ppal-segons-instal3-telf-i-int"                      
## [303] "habit-ppal-segons-nombre-pers-viuen"                       
## [304] "habit-ppal-segons-nom-habit"                               
## [305] "habit-ppal-segons-regim-tin"                               
## [306] "habit-ppal-segons-sup-util"                                
## [307] "horaris-aparcaments-superficie"                            
## [308] "horts-urbans"                                              
## [309] "immobles-quotes-padro-ibi"                                 
## [310] "immo-edif-hab-segons-any-construccio"                      
## [311] "immo-edif-hab-segons-estat-conservacio"                    
## [312] "immo-edif-hab-segons-instalacions"                         
## [313] "immo-edif-hab-segons-num-plantes-sobre-rasant"             
## [314] "immo-edif-hab-segons-num-plantes-sota-rasant"              
## [315] "impacte-de-la-calor"                                       
## [316] "incidents-gestionats-gub"                                  
## [317] "indicadors-transparencia-pressupostaria"                   
## [318] "informacio-estacions-bicing"                               
## [319] "informacio-punts-recarrega-electric"                       
## [320] "informacio-rutes-autobus-estacio-del-nord"                 
## [321] "infraestructures-inventari-bancs"                          
## [322] "infraestructures-inventari-cameres"                        
## [323] "infraestructures-inventari-inscripcions"                   
## [324] "infraestructures-inventari-pas-vianants"                   
## [325] "infraestructures-inventari-pilones"                        
## [326] "infraestructures-inventari-reductors-velocitat"            
## [327] "infraestructures-inventari-reserves"                       
## [328] "infraestructures-inventari-semafors"                       
## [329] "infraestructures-inventari-senyalitzacio"                  
## [330] "infraestructures-inventari-senyals"                        
## [331] "infraestructures-inventari-separa-carrils-bici"            
## [332] "infraestructures-inventari-suports"                        
## [333] "infraestructures-tipologia-inscripcions"                   
## [334] "infraestructures-tipologia-pas-vianants"                   
## [335] "infraestructures-tipologia-semafors"                       
## [336] "infraestructures-tipologia-senyals"                        
## [337] "infraestructures-tipologia-suports-cameres"                
## [338] "intensitat-activitat-turistica"                            
## [339] "iris"                                                      
## [340] "isofones-mapa-estrategic-soroll"                           
## [341] "itineraris"                                                
## [342] "laterals-tallats-transit-bici-bcn"                         
## [343] "lavabos-publics"                                           
## [344] "limits-municipals-districtes"                              
## [345] "llista-exposicions-temporals"                              
## [346] "llocs-culte"                                               
## [347] "lloguer-de-vehicles"                                       
## [348] "locve-evolucio"                                            
## [349] "manteniment-lloguer"                                       
## [350] "mapa-acustic-wms"                                          
## [351] "mapa-ambits-urbanistics-wms"                               
## [352] "mapa-base-de-vialitat"                                     
## [353] "mapa-base-guia"                                            
## [354] "mapa-base-topografic"                                      
## [355] "mapa-construccions-poblament-wms"                          
## [356] "mapa-de-la-malla-de-fulls-utm"                             
## [357] "mapa-de-retolacio-de-carrers"                              
## [358] "mapa-energia-teleco-wms"                                   
## [359] "mapa-graf-viari-carrers-wms"                               
## [360] "mapa-hidrografia-obres-wms"                                
## [361] "mapa-orografia-relleu-wms"                                 
## [362] "mapa-parcelari"                                            
## [363] "mapa-peuat"                                                
## [364] "mapa-planol-ciutat-bcn-wms"                                
## [365] "mapa-serveis-publics-wms"                                  
## [366] "mapa-urbanistic"                                           
## [367] "mapa-usos-sol-wms"                                         
## [368] "mapa-vegetacio-wms"                                        
## [369] "mapa-xarxa-topografica-municipal-wms"                      
## [370] "mapes-immissio-qualitat-aire"                              
## [371] "mediambient-contenidorssal"                                
## [372] "mediambient-puntsrecollidaarbresnadal"                     
## [373] "mediambient-puntsrobaamiga"                                
## [374] "mediambient-puntsverdsbarri"                               
## [375] "mediambient-puntsverdsmobils"                              
## [376] "mediambient-puntverdcolaborador"                           
## [377] "mercats-fires-carrer"                                      
## [378] "mercats-municipals"                                        
## [379] "mesures-estacions-meteorologiques"                         
## [380] "metadades-estacions-meteorologiques"                       
## [381] "metadades-variables-est-meteo"                             
## [382] "mobilitat-quotidiana"                                      
## [383] "modificacions-credit-pressupost"                           
## [384] "modificacions-de-contractes"                               
## [385] "n-edif-hab-n-immo-edif"                                    
## [386] "n-edif-hab-segons-any-construc"                            
## [387] "n-edif-hab-segons-estat-cons-edifici"                      
## [388] "n-edif-hab-segons-instal"                                  
## [389] "n-edif-hab-segons-n-immo"                                  
## [390] "n-edif-hab-segons-nombre-immo"                             
## [391] "n-edif-hab-segons-nombre-plantes"                          
## [392] "n-edif-hab-segons-nombre-plantes-sobre-rasant"             
## [393] "n-edif-hab-segons-nombre-plantes-sota-rasant"              
## [394] "n-edif-hab-segons-n-places-gar"                            
## [395] "n-edif-hab-segons-n-plantes-sobre-rasant"                  
## [396] "n-edif-hab-segons-n-plantes-sota-rasant"                   
## [397] "n-edif-hab-tipus-edif"                                     
## [398] "nomenclator-bcn"                                           
## [399] "np-asia-dipositsvehicles-bcn"                              
## [400] "np-circuits-caminar-correr"                                
## [401] "np-esculleres"                                             
## [402] "np-espais-gimnastica"                                      
## [403] "np-jardins-botanics"                                       
## [404] "np-jardins-interiors-illa"                                 
## [405] "np-molls"                                                  
## [406] "np-nasia-diposits-aigues-pluvials"                         
## [407] "np-nasia-fossars"                                          
## [408] "np-nasia-miradors"                                         
## [409] "np-piscines"                                               
## [410] "np-plantes-depuradores"                                    
## [411] "np-platges"                                                
## [412] "np-quioscs-tramits"                                        
## [413] "np-umbracles"                                              
## [414] "obres"                                                     
## [415] "oferta-publica"                                            
## [416] "ordenances-municipals"                                     
## [417] "pad_alt_mdbas"                                             
## [418] "pad_bai_mdbas"                                             
## [419] "pad_cdo_b_barri-des"                                       
## [420] "pad_def_mdbas"                                             
## [421] "pad-dimensions"                                            
## [422] "pad_dom_mdbas_dones"                                       
## [423] "pad_dom_mdbas_edat-0018"                                   
## [424] "pad_dom_mdbas_edat-1864"                                   
## [425] "pad_dom_mdbas_edat-6599"                                   
## [426] "pad_dom_mdbas_homes"                                       
## [427] "pad_dom_mdbas_nacionalitat"                                
## [428] "pad_dom_mdbas_nacionalitat_edat"                           
## [429] "pad_dom_mdbas_n-persones"                                  
## [430] "pad_dom_mdbas_tipus-domicili"                              
## [431] "pad_dom_mdbas_tipus-domicili_edat"                         
## [432] "pad_emi_mdbas"                                             
## [433] "pad_emi_mdbas_nacionalitat-g"                              
## [434] "pad_imm_mdbas"                                             
## [435] "pad_imm_mdbas_nacionalitat-g"                              
## [436] "pad_m_cognom"                                              
## [437] "pad_mdbas"                                                 
## [438] "pad_mdbas_edat-1"                                          
## [439] "pad_mdbas_edat-q"                                          
## [440] "pad_mdba_sexe_edat-1"                                      
## [441] "pad_mdba_sexe_edat-q"                                      
## [442] "pad_mdbas_lloc-naix_sexe"                                  
## [443] "pad_mdbas_nacionalitat-continent_sexe"                     
## [444] "pad_mdbas_nacionalitat-g_sexe"                             
## [445] "pad_mdbas_niv-educa-esta_sexe"                             
## [446] "pad_mdbas_sexe"                                            
## [447] "pad_mdb_lloc-naix-continent_edat-q_sexe"                   
## [448] "pad_mdb_lloc-naix_edat-q_sexe"                             
## [449] "pad_mdb_lloc-naix-regio_sexe"                              
## [450] "pad_mdb_nacionalitat-contintent_edat-q_sexe"               
## [451] "pad_mdb_nacionalitat-g_edat-q_sexe"                        
## [452] "pad_mdb_nacionalitat-regio_sexe"                           
## [453] "pad_mdb_niv-educa-esta_edat-lloc-naix"                     
## [454] "pad_mdb_niv-educa-esta_edat-q_sexe"                        
## [455] "pad_m_nom_decada_sexe"                                     
## [456] "pad_m_nom_sexe"                                            
## [457] "pad_nai_mdbas"                                             
## [458] "pad_sol_mdb_sexe_edat-q"                                   
## [459] "parades-de-taxi"                                           
## [460] "patis-escolars"                                            
## [461] "patrimoni-arquitectonic-protegit"                          
## [462] "pbd-cataleg-continguts"                                    
## [463] "p-cons-inicials-segons-lgep-loepsf"                        
## [464] "perfil-contractant"                                        
## [465] "piezometres_detall"                                        
## [466] "piezometres_equipaments"                                   
## [467] "plantilla-municipal"                                       
## [468] "plaques-fotovoltaiques"                                    
## [469] "plaques-fotovoltaiques-tipologia"                          
## [470] "poblacio-exposada-mapa-estrategic-soroll"                  
## [471] "poblacio_projectada"                                       
## [472] "poblacio-vulnerable"                                       
## [473] "precipitacio-hist-bcn"                                     
## [474] "prediccio-meteorologica-del-barcelones"                    
## [475] "presencia-absencia-vegetacio"                              
## [476] "pressupost-despeses"                                       
## [477] "pressupost-ingressos"                                      
## [478] "prorrogues-de-contractes"                                  
## [479] "provisio-promocio"                                         
## [480] "proximitat-espais-verds"                                   
## [481] "punts-ancoratge-bicicletes"                                
## [482] "punts-critics-neteja-barcelona"                            
## [483] "punts-informacio-turistica"                                
## [484] "punts-recarrega-vehicles-electrics"                        
## [485] "punts-verds"                                               
## [486] "punts-wifi"                                                
## [487] "qualificacions-elements-urbanistics"                       
## [488] "qualitat-aire-detall-bcn"                                  
## [489] "qualitat-aire-estacions-bcn"                               
## [490] "rasters-mapa-estrategic-soroll"                            
## [491] "rebuts-quota-padro-iae"                                    
## [492] "rebuts-quota-padro-vetlladors-terrasses"                   
## [493] "recintes-gran-aforament"                                   
## [494] "registre-de-convenis"                                      
## [495] "registre-estudis-i-informes"                               
## [496] "relacio-contractistes"                                     
## [497] "renda-disponible-llars-bcn"                                
## [498] "renda-tributaria-per-persona-atlas-distribucio"            
## [499] "renda-tributaria-unitat-consum-atlas-distribucio"          
## [500] "resums-trimestrals-contractacio"                           
## [501] "risc-contaminacio-acustica"                                
## [502] "ronda-verda"                                               
## [503] "sanitat-farmacies"                                         
## [504] "sanitat-hospitals-atencio-primaria"                        
## [505] "sanitat-serveis-sanitaris"                                 
## [506] "servei-cataleg-metadades-csw"                              
## [507] "serveissocials-centresdiagentgran"                         
## [508] "serveissocials-centresserveissocials"                      
## [509] "serveissocials-equipsatencioinfanciaadolescencia"          
## [510] "serveissocials-habitatgestutelats"                         
## [511] "serveissocials-menjadorssocials"                           
## [512] "serveissocials-oficinesbenestarsocial"                     
## [513] "serveissocials-puntsassessoramentenergetic"                
## [514] "serveissocials-puntsinformacioiatenciodones"               
## [515] "serveissocials-residenciesgentgran"                        
## [516] "subvencions-a-ens-publics-no-integrats-cercador-post-2019" 
## [517] "subvencions-atorgades-ajuntament-i-instituts"              
## [518] "subvencions_entitats_nfge"                                 
## [519] "subvencions-i-transferencies-a-ens-publics"                
## [520] "subvencions-transferencies-cultura"                        
## [521] "tanatoris"                                                 
## [522] "tarifes-aparcament-superficie"                             
## [523] "taula-direle"                                              
## [524] "taula-direle-sec-cens"                                     
## [525] "taula-map-illa"                                            
## [526] "taula-segimon"                                             
## [527] "teleferics"                                                
## [528] "temperatures-hist-bcn"                                     
## [529] "terrasses-comercos-vigents"                                
## [530] "tramer-mapa-estrategic-soroll"                             
## [531] "trams"                                                     
## [532] "trams-aparcament-superficie"                               
## [533] "transferencies-encomanes-gestio"                           
## [534] "transitaeri_flightradar_ppal_aeroport"                     
## [535] "transitaeri_flightradar_ppal_comp_zona"                    
## [536] "transitaeri_flightradar_ppal_pais"                         
## [537] "transit-relacio-trams"                                     
## [538] "transit-relacio-trams-per-itinerari"                       
## [539] "transports"                                                
## [540] "transports-metropolitants-companyies-autocars-de-barcelona"
## [541] "us-del-servei-bicing"                                      
## [542] "viatges-govern-bcn"                                        
## [543] "vies-ciclables"                                            
## [544] "xarxa-refugis-climatics"                                   
## [545] "xarxasoroll-equipsmonitor-dades"                           
## [546] "xarxasoroll-equipsmonitor-instal"                          
## [547] "zbe-ambit"                                                 
## [548] "zones30-carrers"                                           
## [549] "zones-carrega-descarrega"                                  
## [550] "zones-estacionament-zona-bus"

For later use, I will need information about air quality stations:

st_package <- package_show("qualitat-aire-estacions-bcn")

The resources element of the package shows relevant information about each resource of the package:

st_package$resources[[1]]
## $cache_last_updated
## NULL
## 
## $incorporated_in_cityos_res
## [1] "No"
## 
## $token_type
## [1] ""
## 
## $package_id
## [1] "4dff88b1-151b-48db-91c2-45007cd5d07a"
## 
## $datastore_active
## [1] TRUE
## 
## $id
## [1] "d1aa40d7-66f9-451b-85f8-955b765fdc2f"
## 
## $api_access_number_absolute
## [1] "52"
## 
## $token_name
## [1] ""
## 
## $state
## [1] "active"
## 
## $api_access_number
## [1] "22"
## 
## $size
## [1] "8494"
## 
## $token_required
## [1] "No"
## 
## $hash
## [1] ""
## 
## $description
## [1] ""
## 
## $format
## [1] "CSV"
## 
## $downloads
## [1] "166"
## 
## $mimetype_inner
## NULL
## 
## $url_type
## [1] "upload"
## 
## $token_provider
## [1] ""
## 
## $column_types
## [1] ""
## 
## $hide_url
## [1] "No"
## 
## $token_version
## [1] ""
## 
## $mimetype
## NULL
## 
## $cache_url
## NULL
## 
## $name
## [1] "2025_qualitat_aire_estacions.csv"
## 
## $created
## [1] "2025-02-12T09:21:21.936318"
## 
## $url
## [1] "https://opendata-ajuntament.barcelona.cat/data/dataset/4dff88b1-151b-48db-91c2-45007cd5d07a/resource/d1aa40d7-66f9-451b-85f8-955b765fdc2f/download/2025_qualitat_aire_estacions.csv"
## 
## $downloads_absolute
## [1] "670"
## 
## $map_visualization_res
## [1] "data_explorer_map"
## 
## $qa
## $qa$updated
## [1] "2025-07-27T02:12:17.690430"
## 
## $qa$openness_score
## [1] 3
## 
## $qa$archival_timestamp
## NULL
## 
## $qa$format
## [1] "CSV"
## 
## $qa$created
## [1] "2025-02-13T02:11:06.806242"
## 
## $qa$resource_timestamp
## NULL
## 
## $qa$openness_score_reason
## [1] "This file had not been downloaded at the time of scoring it. URL extension \"csv\" relates to format \"CSV\" and receives score: 3."
## 
## 
## $last_modified
## [1] "2025-02-12T09:21:21.669919"
## 
## $position
## [1] 0
## 
## $revision_id
## [1] "48b2f855-84a4-4dbb-8544-6ac1dcfc9236"
## 
## $resource_type
## NULL

The url element contains an URL to read a .csv file. I am reading the file and transform it on the fly to obtain the stations table.

stations <- read_csv(st_package$resources[[1]]$url)
## Rows: 55 Columns: 15
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (7): nom_cabina, codi_dtes, ubicacio, Nom_districte, Nom_barri, Clas_1, ...
## dbl (8): Estacio, zqa, codi_eoi, Longitud, Latitud, Codi_districte, Codi_bar...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
stations <- stations |>
  clean_names() |>
  mutate(nom_cabina = str_replace(nom_cabina, "Observatori", "Observ")) |>
  select(estacio, nom_cabina) |>
  distinct()

stations
## # A tibble: 8 × 2
##   estacio nom_cabina              
##     <dbl> <chr>                   
## 1       4 Barcelona - Poblenou    
## 2      42 Barcelona - Sants       
## 3      43 Barcelona - Eixample    
## 4      44 Barcelona - Gràcia      
## 5      50 Barcelona - Ciutadella  
## 6      54 Barcelona - Vall Hebron 
## 7      57 Barcelona - Palau Reial 
## 8      58 Barcelona - Observ Fabra

Air quality data are found at the qualitat-aire-detall-bcn package:

aq_package <- package_show("qualitat-aire-detall-bcn")

Let’s take a look at the resources content for this package:

aq_package$resources[[1]]
## $cache_last_updated
## NULL
## 
## $package_id
## [1] "0582a266-ea06-4cc5-a219-913b22484e40"
## 
## $datastore_active
## [1] FALSE
## 
## $id
## [1] "c2032e7c-10ee-4c69-84d3-9e8caf9ca97a"
## 
## $api_access_number_absolute
## [1] "6518"
## 
## $state
## [1] "active"
## 
## $api_access_number
## [1] "657"
## 
## $size
## [1] "49176"
## 
## $token_required
## [1] "No"
## 
## $hash
## [1] ""
## 
## $description
## [1] ""
## 
## $format
## [1] "CSV"
## 
## $downloads
## [1] "16568"
## 
## $mimetype_inner
## NULL
## 
## $url_type
## [1] ""
## 
## $column_types
## [1] ""
## 
## $file_volum
## [1] "little"
## 
## $mimetype
## NULL
## 
## $cache_url
## NULL
## 
## $name
## [1] "Qualitat_Aire_Detall.csv"
## 
## $created
## [1] "2018-05-23T15:10:28.678748"
## 
## $url
## [1] "https://opendata-ajuntament.barcelona.cat/data/dataset/0582a266-ea06-4cc5-a219-913b22484e40/resource/c2032e7c-10ee-4c69-84d3-9e8caf9ca97a/download"
## 
## $downloads_absolute
## [1] "647315"
## 
## $map_visualization_res
## [1] "none"
## 
## $qa
## $qa$updated
## [1] "2025-07-27T02:12:15.037481"
## 
## $qa$openness_score
## [1] 3
## 
## $qa$archival_timestamp
## NULL
## 
## $qa$format
## [1] "CSV"
## 
## $qa$created
## [1] "2018-05-24T02:07:27.871534"
## 
## $qa$resource_timestamp
## NULL
## 
## $qa$openness_score_reason
## [1] "This file had not been downloaded at the time of scoring it. URL extension \"csv\" relates to format \"CSV\" and receives score: 3."
## 
## 
## $last_modified
## [1] "2021-06-11T05:43:54"
## 
## $position
## [1] 0
## 
## $revision_id
## [1] "85fa0dd9-b217-45df-b586-0397afeac607"
## 
## $resource_type
## NULL

Some tables are in .csv format and others in .7z format. We need only the .csv formats. To do so:

  • The is_csv logical vector identifies which resources are .csv files.
  • The urls_csv list includes the URLs of the resouces that are .csv files.
is_csv <- map_lgl(aq_package$resources, ~ .$format == "CSV")
urls_csv <- map(aq_package$resources[which(is_csv)], ~ .$url) # urls de los 85 .csv

First Reading of Data

Let’s start reading all the .csv files of air quality data included in the package. Then, I will name each resource with the name of its file.

airqual_all <- map(urls_csv, read_csv)
## Rows: 280 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (29): CODI_PROVINCIA, PROVINCIA, CODI_MUNICIPI, MUNICIPI, ESTACIO, V01, ...
## dbl (28): CODI_CONTAMINANT, ANY, MES, DIA, H01, H02, H03, H04, H05, H06, H07...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2170 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1960 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2170 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2030 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1750 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1987 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1856 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1984 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1920 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1984 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1870 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2077 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2077 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2010 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2077 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2052 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2170 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2015 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1820 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2029 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1980 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2046 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1980 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2039 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2015 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1950 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2015 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1950 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2015 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1705 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1562 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1987 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1950 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2015 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1950 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2015 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2015 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1950 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2015 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1950 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 2015 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1519 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1372 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1519 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1480 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1674 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1620 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1674 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1674 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1620 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1674 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1587 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1705 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1279 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1305 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1395 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1378 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1519 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1470 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1519 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1372 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1470 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1519 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1274 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1519 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 5904 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (15): nom_cabina, qualitat_aire, codi_dtes, zqa, codi_eoi, hora_o3, qual...
## dbl  (3): longitud, latitud, dateTime
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 5376 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (15): nom_cabina, qualitat_aire, codi_dtes, zqa, codi_eoi, hora_o3, qual...
## dbl  (3): longitud, latitud, dateTime
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 5928 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (9): nom_cabina, qualitat_aire, codi_dtes, zqa, codi_eoi, hora_pm10, qua...
## dbl (3): longitud, latitud, dateTime
## lgl (6): hora_o3, qualitat_o3, valor_o3, hora_no2, qualitat_no2, valor_no2
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1131 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (28): CODI_PROVINCIA, PROVINCIA, CODI_MUNICIPI, MUNICIPI, V01, V02, V03,...
## dbl (29): ESTACIO, CODI_CONTAMINANT, ANY, MES, DIA, H01, H02, H03, H04, H05,...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1092 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (28): CODI_PROVINCIA, PROVINCIA, CODI_MUNICIPI, MUNICIPI, V01, V02, V03,...
## dbl (29): ESTACIO, CODI_CONTAMINANT, ANY, MES, DIA, H01, H02, H03, H04, H05,...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1164 Columns: 1
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): CODI_PROVINCIA;PROVINCIA;CODI_MUNICIPI;MUNICIPI;ESTACIO;CODI_CONTAM...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1053 Columns: 1
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): CODI_PROVINCIA;PROVINCIA;CODI_MUNICIPI;MUNICIPI;ESTACIO;CODI_CONTAM...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1209 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1131 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1209 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1215 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 1276 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (26): PROVINCIA, MUNICIPI, V01, V02, V03, V04, V05, V06, V07, V08, V09, ...
## dbl (31): CODI_PROVINCIA, CODI_MUNICIPI, ESTACIO, CODI_CONTAMINANT, ANY, MES...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 3262 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (15): nom_cabina, qualitat_aire, codi_dtes, zqa, codi_eoi, hora_o3, qual...
## dbl  (3): longitud, latitud, dateTime
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 3649 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (15): nom_cabina, qualitat_aire, codi_dtes, zqa, codi_eoi, hora_o3, qual...
## dbl  (3): longitud, latitud, dateTime
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 5800 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (15): nom_cabina, qualitat_aire, codi_dtes, zqa, codi_eoi, hora_o3, qual...
## dbl  (3): longitud, latitud, dateTime
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 5736 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (15): nom_cabina, qualitat_aire, codi_dtes, zqa, codi_eoi, hora_o3, qual...
## dbl  (3): longitud, latitud, dateTime
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 5944 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (15): nom_cabina, qualitat_aire, codi_dtes, zqa, codi_eoi, hora_o3, qual...
## dbl  (3): longitud, latitud, dateTime
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 5744 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (15): nom_cabina, qualitat_aire, codi_dtes, zqa, codi_eoi, hora_o3, qual...
## dbl  (3): longitud, latitud, dateTime
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 5848 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (15): nom_cabina, qualitat_aire, codi_dtes, zqa, codi_eoi, hora_o3, qual...
## dbl  (3): longitud, latitud, dateTime
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
names(airqual_all) <- map_chr(aq_package$resources[which(is_csv)], ~ .$name)

The output of readr::read:csv() shows that tables are presented in different structures. To detect the differeet tipologies, I have examined how many columns has the table of each resource.

columns <- map_int(airqual_all, ncol)
columns
##               Qualitat_Aire_Detall.csv    2025_01_Gener_qualitat_aire_BCN.csv 
##                                     57                                     57 
##   2025_02_Febrer_qualitat_aire_BCN.csv     2025_03_Marc_qualitat_aire_BCN.csv 
##                                     57                                     57 
##    2025_04_Abril_qualitat_aire_BCN.csv     2025_06_Juny_qualitat_aire_BCN.csv 
##                                     57                                     57 
##    2024_01_Gener_qualitat_aire_BCN.csv   2024_02_Febrer_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2024_03_Marc_qualitat_aire_BCN.csv    2024_04_Abril_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2024_05_Maig_qualitat_aire_BCN.csv     2024_06_Juny_qualitat_aire_BCN.csv 
##                                     57                                     57 
##   2024_07_Juliol_qualitat_aire_BCN.csv    2024_08_Agost_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2024_09_Setembre_qualitat_aire_BCN.csv  2024_10_Octubre_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2024_11_Novembre_qualitat_aire_BCN.csv 2024_12_Desembre_qualitat_aire_BCN.csv 
##                                     57                                     57 
##    2023_01_Gener_qualitat_aire_BCN.csv   2023_02_Febrer_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2023_03_Marc_qualitat_aire_BCN.csv    2023_04_Abril_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2023_05_Maig_qualitat_aire_BCN.csv     2023_06_Juny_qualitat_aire_BCN.csv 
##                                     57                                     57 
##   2023_07_Juliol_qualitat_aire_BCN.csv    2023_08_Agost_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2023_09_Setembre_qualitat_aire_BCN.csv  2023_10_Octubre_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2023_11_Novembre_qualitat_aire_BCN.csv 2023_12_Desembre_qualitat_aire_BCN.csv 
##                                     57                                     57 
##    2022_01_Gener_qualitat_aire_BCN.csv   2022_02_Febrer_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2022_03_Marc_qualitat_aire_BCN.csv    2022_04_Abril_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2022_05_Maig_qualitat_aire_BCN.csv     2022_06_Juny_qualitat_aire_BCN.csv 
##                                     57                                     57 
##   2022_07_Juliol_qualitat_aire_BCN.csv    2022_08_Agost_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2022_09_Setembre_qualitat_aire_BCN.csv  2022_10_Octubre_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2022_11_Novembre_qualitat_aire_BCN.csv 2022_12_Desembre_qualitat_aire_BCN.csv 
##                                     57                                     57 
##    2021_01_Gener_qualitat_aire_BCN.csv   2021_02_Febrer_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2021_03_Marc_qualitat_aire_BCN.csv    2021_04_Abril_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2021_05_Maig_qualitat_aire_BCN.csv     2021_06_Juny_qualitat_aire_BCN.csv 
##                                     57                                     57 
##   2021_07_Juliol_qualitat_aire_BCN.csv    2021_08_Agost_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2021_09_Setembre_qualitat_aire_BCN.csv  2021_10_Octubre_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2021_11_Novembre_qualitat_aire_BCN.csv 2021_12_Desembre_qualitat_aire_BCN.csv 
##                                     57                                     57 
##    2020_01_Gener_qualitat_aire_BCN.csv   2020_02_Febrer_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2020_03_Marc_qualitat_aire_BCN.csv    2020_04_Abril_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2020_05_Maig_qualitat_aire_BCN.csv     2020_06_Juny_qualitat_aire_BCN.csv 
##                                     57                                     57 
##   2020_07_Juliol_qualitat_aire_BCN.csv    2020_08_Agost_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2020_09_Setembre_qualitat_aire_BCN.csv  2020_10_Octubre_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2020_11_Novembre_qualitat_aire_BCN.csv 2020_12_Desembre_qualitat_aire_BCN.csv 
##                                     57                                     57 
##    2019_01_Gener_qualitat_aire_BCN.csv   2019_02_Febrer_qualitat_aire_BCN.csv 
##                                     18                                     18 
##     2019_03_Marc_qualitat_aire_BCN.csv    2019_04_Abril_qualitat_aire_BCN.csv 
##                                     18                                     57 
##     2019_05_Maig_qualitat_aire_BCN.csv     2019_06_Juny_qualitat_aire_BCN.csv 
##                                     57                                      1 
##   2019_07_Juliol_qualitat_aire_BCN.csv    2019_08_Agost_qualitat_aire_BCN.csv 
##                                      1                                     57 
## 2019_09_Setembre_qualitat_aire_BCN.csv  2019_10_Octubre_qualitat_aire_BCN.csv 
##                                     57                                     57 
## 2019_11_Novembre_qualitat_aire_BCN.csv 2019_12_Desembre_qualitat_aire_BCN.csv 
##                                     57                                     57 
##     2018_06_Juny_qualitat_aire_BCN.csv   2018_07_Juliol_qualitat_aire_BCN.csv 
##                                     18                                     18 
##    2018_08_Agost_qualitat_aire_BCN.csv 2018_09_Setembre_qualitat_aire_BCN.csv 
##                                     18                                     18 
##  2018_10_Octubre_qualitat_aire_BCN.csv 2018_11_Novembre_qualitat_aire_BCN.csv 
##                                     18                                     18 
## 2018_12_Desembre_qualitat_aire_BCN.csv 
##                                     18

We can detect three different tipologies:

  • The most common has 57 columns, and has been maintained since 2020.
  • The tables of June and July 2019 have only one column. This suggests that the separators of the .csv are the semicolon rather than comma.
  • Early versions of the dataset have a configuration of 18 columns.

Furthermore, the table of May 2025 is not present in the resource for some reason at the present date. This table is also not available in the website.

I start storing the datasets of 57 columns in the airqual_csv list

airqual_csv <- airqual_all[which(columns == 57)]

Let’s examine one of the datasets with one column:

airqual_all$`2019_07_Juliol_qualitat_aire_BCN.csv`
## # A tibble: 1,053 × 1
##    CODI_PROVINCIA;PROVINCIA;CODI_MUNICIPI;MUNICIPI;ESTACIO;CODI_CONTAMINANT;AN…¹
##    <chr>                                                                        
##  1 08;Barcelona;019;Barcelona;4;7;2019;7;1;1;V;1;V;1;V;1;V;1;V;2;V;5;V;23;V;23;…
##  2 08;Barcelona;019;Barcelona;4;7;2019;7;2;2;V;3;V;3;V;2;V;4;V;6;V;6;V;29;V;24;…
##  3 08;Barcelona;019;Barcelona;4;7;2019;7;3;2;V;2;V;4;V;6;V;5;V;6;V;15;V;40;V;40…
##  4 08;Barcelona;019;Barcelona;4;7;2019;7;4;7;V;4;V;4;V;2;V;2;V;3;V;6;V;16;V;31;…
##  5 08;Barcelona;019;Barcelona;4;7;2019;7;5;1;V;1;V;1;V;2;V;3;V;5;V;11;V;23;V;36…
##  6 08;Barcelona;019;Barcelona;4;7;2019;7;6;3;V;2;V;3;V;3;V;2;V;3;V;4;V;5;V;9;V;…
##  7 08;Barcelona;019;Barcelona;4;7;2019;7;7;12;V;4;V;2;V;1;V;2;V;10;V;11;V;12;V;…
##  8 08;Barcelona;019;Barcelona;4;7;2019;7;8;2;V;2;V;4;V;2;V;1;V;3;V;3;V;21;V;48;…
##  9 08;Barcelona;019;Barcelona;4;7;2019;7;9;9;V;7;V;3;V;2;V;1;V;1;V;2;V;3;V;4;V;…
## 10 08;Barcelona;019;Barcelona;4;7;2019;7;10;2;V;2;V;1;V;1;V;2;V;3;V;2;V;5;V;9;V…
## # ℹ 1,043 more rows
## # ℹ abbreviated name:
## #   ¹​`CODI_PROVINCIA;PROVINCIA;CODI_MUNICIPI;MUNICIPI;ESTACIO;CODI_CONTAMINANT;ANY;MES;DIA;H01;V01;H02;V02;H03;V03;H04;V04;H05;V05;H06;V06;H07;V07;H08;V08;H09;V09;H10;V10;H11;V11;H12;V12;H13;V13;H14;V14;H15;V15;H16;V16;H17;V17;H18;V18;H19;V19;H20;V20;H21;V21;H22;V22;H23;V23;H24;V24`

We confirm that this dataset is quite similar to the 57 columns, but it really uses semicolon as separator. It is enough with reading them with readr::read_csv2(). The result is stored in the airqual_csv2 list.

urls_csv2 <- urls_csv[which(columns == 1)]
airqual_csv2 <- map(urls_csv2, read_csv2)
## ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
## Rows: 1164 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (52): CODI_PROVINCIA, PROVINCIA, CODI_MUNICIPI, MUNICIPI, H01, V01, H02,...
## dbl  (5): ESTACIO, CODI_CONTAMINANT, ANY, MES, DIA
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
## 
## Rows: 1053 Columns: 57
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (52): CODI_PROVINCIA, PROVINCIA, CODI_MUNICIPI, MUNICIPI, H01, V01, H02,...
## dbl  (5): ESTACIO, CODI_CONTAMINANT, ANY, MES, DIA
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
names(airqual_csv2) <- names(airqual_csv[which(columns == 1)])

The tables with 18 columns have a completely different structure.

airqual_all$`2019_02_Febrer_qualitat_aire_BCN.csv`
## # A tibble: 5,376 × 18
##    nom_cabina    qualitat_aire codi_dtes zqa   codi_eoi longitud latitud hora_o3
##    <chr>         <chr>         <chr>     <chr> <chr>       <dbl>   <dbl> <chr>  
##  1 Barcelona - … --            ID        01    08019042     2.13    41.4 <NA>   
##  2 Barcelona - … --            IH        01    08019043     2.15    41.4 <NA>   
##  3 Barcelona - … --            IJ        01    08019044     2.15    41.4 <NA>   
##  4 Barcelona - … --            IL        01    08019050     2.19    41.4 <NA>   
##  5 Barcelona - … --            IN        01    08019054     2.15    41.4 <NA>   
##  6 Barcelona - … --            IZ        01    08019057     2.12    41.4 <NA>   
##  7 Barcelona - … --            I2        01    08019004     2.20    41.4 <NA>   
##  8 Barcelona - … --            OF        01    08019058     2.12    41.4 <NA>   
##  9 Barcelona - … Bona          ID        01    08019042     2.13    41.4 <NA>   
## 10 Barcelona - … Bona          IH        01    08019043     2.15    41.4 0h     
## # ℹ 5,366 more rows
## # ℹ 10 more variables: qualitat_o3 <chr>, valor_o3 <chr>, hora_no2 <chr>,
## #   qualitat_no2 <chr>, valor_no2 <chr>, hora_pm10 <chr>, qualitat_pm10 <chr>,
## #   valor_pm10 <chr>, generat <chr>, dateTime <dbl>

They will require being treated separatedly so they are stored in the airqual_long dataset.

airqual_long <- airqual_all[which(columns == 18)]

To summarise, we have now three different sets of tables:

  • airqual_csv, including the most common structure of 57 columns and obtained from a comma-separated file.
  • airqual_csv2, including tables with a similar structure of 57 columns, obtained form a semicolon-separated file.
  • airqual_long, including the tables with the old standard of 18 columns.

Table Cleaning

Now we need to tidy the three diferents sets of tables, so they have the same columns and can be integrated in a single dataset.

I presented how to deal with airqual_csv tables in a previous post. There I defined a clean_aq_table function to transform the table in tidy format.

clean_aq_table <- function(table){
  t <- table |>
  clean_names() |>
  select(c(estacio:dia, starts_with("h"))) |>
  mutate(estacio = as.numeric(estacio)) |>
  pivot_longer(-c(estacio:dia), names_prefix = "h", 
               names_to = "hora", values_to = "value") |>
  mutate(hora = as.numeric(hora)) |>
  mutate(datetime = make_datetime(year = any, month = mes, day = dia, hour = hora)) |>
  relocate(datetime, .after = codi_contaminant)
  
  return(t)
}

I am applying the function to all the tables of airqual_csv and wrapping all together in a single table using purrr::map_dfr().

airqual_csv_table <- map_dfr(airqual_csv, clean_aq_table)

Here is the resulting table:

airqual_csv_table
## # A tibble: 3,019,368 × 8
##    estacio codi_contaminant datetime              any   mes   dia  hora value
##      <dbl>            <dbl> <dttm>              <dbl> <dbl> <dbl> <dbl> <dbl>
##  1      43              999 2025-07-24 01:00:00  2025     7    24     1  16.2
##  2      43              999 2025-07-24 02:00:00  2025     7    24     2  17.1
##  3      43              999 2025-07-24 03:00:00  2025     7    24     3  16.8
##  4      43              999 2025-07-24 04:00:00  2025     7    24     4  16.4
##  5      43              999 2025-07-24 05:00:00  2025     7    24     5  18.8
##  6      43              999 2025-07-24 06:00:00  2025     7    24     6  15.8
##  7      43              999 2025-07-24 07:00:00  2025     7    24     7  13.6
##  8      43              999 2025-07-24 08:00:00  2025     7    24     8  12.8
##  9      43              999 2025-07-24 09:00:00  2025     7    24     9  16.1
## 10      43              999 2025-07-24 10:00:00  2025     7    24    10  15.5
## # ℹ 3,019,358 more rows

The airqual_csv2 tables have a slightly different structure regarding the data types of the estacio and value columns, so here is a clean_aq_table2 specific for them:

clean_aq_table2 <- function(table){
  table |> 
  clean_names() |>
  select(c(estacio:dia, starts_with("h"))) |>
  pivot_longer(-c(estacio:dia), names_prefix = "h", 
               names_to = "hora", values_to = "value")  |>
  mutate(hora = as.numeric(hora)) |>
  mutate(datetime = make_datetime(year = any, month = mes, day = dia, hour = hora)) |>
  mutate(value = as.numeric(value)) |>
  relocate(datetime, .after = codi_contaminant)
}

Here is the result of the data cleaning. The column names and types are the same as the airqual_csv_table.

airqual_csv2_table <- map_dfr(airqual_csv2, clean_aq_table2)
airqual_csv2_table
## # A tibble: 53,208 × 8
##    estacio codi_contaminant datetime              any   mes   dia  hora value
##      <dbl>            <dbl> <dttm>              <dbl> <dbl> <dbl> <dbl> <dbl>
##  1       4                7 2019-06-01 01:00:00  2019     6     1     1     7
##  2       4                7 2019-06-01 02:00:00  2019     6     1     2    15
##  3       4                7 2019-06-01 03:00:00  2019     6     1     3     5
##  4       4                7 2019-06-01 04:00:00  2019     6     1     4    28
##  5       4                7 2019-06-01 05:00:00  2019     6     1     5    14
##  6       4                7 2019-06-01 06:00:00  2019     6     1     6     7
##  7       4                7 2019-06-01 07:00:00  2019     6     1     7     9
##  8       4                7 2019-06-01 08:00:00  2019     6     1     8    12
##  9       4                7 2019-06-01 09:00:00  2019     6     1     9    17
## 10       4                7 2019-06-01 10:00:00  2019     6     1    10    32
## # ℹ 53,198 more rows

The elements of airqual_long are harder to tidy:

airqual_long[[1]]
## # A tibble: 5,904 × 18
##    nom_cabina    qualitat_aire codi_dtes zqa   codi_eoi longitud latitud hora_o3
##    <chr>         <chr>         <chr>     <chr> <chr>       <dbl>   <dbl> <chr>  
##  1 Barcelona - … Bona          ID        01    08019042     2.13    41.4 <NA>   
##  2 Barcelona - … Regular       IH        01    08019043     2.15    41.4 23h    
##  3 Barcelona - … Regular       IJ        01    08019044     2.15    41.4 23h    
##  4 Barcelona - … Bona          IL        01    08019050     2.19    41.4 23h    
##  5 Barcelona - … Bona          IN        01    08019054     2.15    41.4 23h    
##  6 Barcelona - … Bona          IZ        01    08019057     2.12    41.4 0h     
##  7 Barcelona - … Bona          I2        01    08019004     2.20    41.4 <NA>   
##  8 Barcelona - … Bona          OF        01    08019058     2.12    41.4 0h     
##  9 Barcelona - … Regular       ID        01    08019042     2.13    41.4 <NA>   
## 10 Barcelona - … Regular       IH        01    08019043     2.15    41.4 0h     
## # ℹ 5,894 more rows
## # ℹ 10 more variables: qualitat_o3 <chr>, valor_o3 <chr>, hora_no2 <chr>,
## #   qualitat_no2 <chr>, valor_no2 <chr>, hora_pm10 <chr>, qualitat_pm10 <chr>,
## #   valor_pm10 <chr>, generat <chr>, dateTime <dbl>

The function tidying these datasets is clean_aq_table(), presented below. The measurement stations and pollutants are presented with their names, and not with their code. That’s why I have defined the stations table at the beginning. These tables include only three pollutants. Their codes are presented in the conts table inside the function.

clean_aq_long <- function(table){
table0 <- table |>
  select(nom_cabina, starts_with("hora"), starts_with("valor"), generat) |>
  mutate(across(starts_with("valor"), ~ str_replace(., " µg/m³", ""))) |>
  mutate(across(starts_with("valor"), ~ str_replace(., "--", ""))) |>
  mutate(across(starts_with("valor"), ~ ifelse(. == "", NA, .))) |>
  mutate(datetime = dmy_hm(generat)) |>
  select(nom_cabina, datetime, starts_with("valor"))
  
  new_table <- map_dfr(c("o3", "no2", "pm10"), ~ table0 |>
      select(nom_cabina, datetime, ends_with(.)) |>
      mutate(contaminant = .) |>
      mutate(across(starts_with("valor"), ~ as.numeric(.))) |>
      rename(c("value" = paste0("valor_", .))))
    
  conts <- tibble(contaminant = c("o3", "no2", "pm10"),
                codi_contaminant = c(14, 8, 10))

  new_table <- new_table |>
  left_join(conts, by = "contaminant")

  new_table <- new_table |>
    left_join(stations |> select(estacio, nom_cabina), by = "nom_cabina")
  
  new_table <- new_table |>
    mutate(any = year(datetime), mes = month(datetime),
           dia = day(datetime), hora = hour(datetime)) |>
    select(estacio, codi_contaminant, datetime, any, mes, dia, hora, value)
  
  return(new_table)
  }

The table of February 2019 was totally empty of data, so it has been excluded from treatment. When applying clean_aq_long() some warnings appeared resulting from applying as.numeric() to the column of values, indicating that non-numeric strings have been turned into NA by coertion.

airqual_long_table <- map_dfr(airqual_long[c(1, 4:10)], clean_aq_long)
airqual_long_table
## # A tibble: 125,661 × 8
##    estacio codi_contaminant datetime              any   mes   dia  hora value
##      <dbl>            <dbl> <dttm>              <dbl> <dbl> <int> <int> <dbl>
##  1      42               14 2019-01-01 00:00:00  2019     1     1     0    NA
##  2      43               14 2019-01-01 00:00:00  2019     1     1     0     3
##  3      44               14 2019-01-01 00:00:00  2019     1     1     0     3
##  4      50               14 2019-01-01 00:00:00  2019     1     1     0     2
##  5      54               14 2019-01-01 00:00:00  2019     1     1     0    10
##  6      57               14 2019-01-01 00:00:00  2019     1     1     0     1
##  7       4               14 2019-01-01 00:00:00  2019     1     1     0    NA
##  8      58               14 2019-01-01 00:00:00  2019     1     1     0    86
##  9      42               14 2019-01-01 01:00:00  2019     1     1     1    NA
## 10      43               14 2019-01-01 01:00:00  2019     1     1     1     4
## # ℹ 125,651 more rows

Wrapping It All Together

Now that we have the three sets of tables turned into a single dataset, it is time to wrap them up with the dplyr::bind_rows() function. It has worked properly because similar data has the same column name and data type in the three tables.

airqual <- bind_rows(airqual_csv_table, airqual_csv2_table, airqual_long_table)

Finally, I am renaming columns so that they are presented in the same language.

airqual <- airqual |>
  rename(station = estacio, pollutant = codi_contaminant, year = any, month = mes, day = dia, hour = hora)

This is the resulting dataset, including air quality data from 2018 to mid 2025.

airqual
## # A tibble: 3,198,237 × 8
##    station pollutant datetime             year month   day  hour value
##      <dbl>     <dbl> <dttm>              <dbl> <dbl> <dbl> <dbl> <dbl>
##  1      43       999 2025-07-24 01:00:00  2025     7    24     1  16.2
##  2      43       999 2025-07-24 02:00:00  2025     7    24     2  17.1
##  3      43       999 2025-07-24 03:00:00  2025     7    24     3  16.8
##  4      43       999 2025-07-24 04:00:00  2025     7    24     4  16.4
##  5      43       999 2025-07-24 05:00:00  2025     7    24     5  18.8
##  6      43       999 2025-07-24 06:00:00  2025     7    24     6  15.8
##  7      43       999 2025-07-24 07:00:00  2025     7    24     7  13.6
##  8      43       999 2025-07-24 08:00:00  2025     7    24     8  12.8
##  9      43       999 2025-07-24 09:00:00  2025     7    24     9  16.1
## 10      43       999 2025-07-24 10:00:00  2025     7    24    10  15.5
## # ℹ 3,198,227 more rows

Evolution of PM10 at the Eixample Station

Now that we have all data into a single table, we can examine some of the results. For instance, here is the evolution of the PM10 pollutant in the Eixample air quality measurement station (code 43).

airqual |>
  filter(station == 43, pollutant == 10) |>
  mutate(date = as_date(datetime)) |>
  group_by(date) |>
  summarise(pm10 = mean(value, na.rm = TRUE), .groups = "drop") |>
  ggplot(aes(date, pm10)) +
  geom_line(linewidth = 0.5) +
  theme_minimal() +
  labs(title = "Evolution of PM10 at Eixample Station (2018-2025)", x = NULL, y = NULL)
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_line()`).

As the year 2022 had high values of PM10, we can observe it closely:

airqual |>
  filter(station == 43, pollutant == 10, year == 2022) |>
  mutate(date = as_date(datetime)) |>
  group_by(date) |>
  summarise(pm10 = mean(value, na.rm = TRUE), .groups = "drop") |>
  ggplot(aes(date, pm10)) +
  geom_line(linewidth = 0.5) +
  geom_hline(yintercept = 50, color = "red", linetype = "dashed") +
  theme_minimal() +
  labs(title = "Evolution of PM10 at Eixample Station (2022)", x = NULL, y = NULL)

Episodes of PM10 Pollution

One of the ways of defining an episode of PM10 pollution is to observe daily average values of PM10 above 50 in two or more station. Let’s see the days when one of these episodes occurred.

pm10_episodes <- airqual |>
  filter(pollutant == 10) |>
  mutate(date = as_date(datetime)) |>
  group_by(date, station) |>
  summarise(pm10 = mean(value, na.rm = TRUE), .groups = "drop") |>
  filter(pm10 >= 50) |>
  group_by(date) |>
  summarise(n = n()) |>
  filter(n > 1) |>
  arrange(-n)

pm10_episodes
## # A tibble: 46 × 2
##    date           n
##    <date>     <int>
##  1 2019-12-17     6
##  2 2019-12-18     6
##  3 2020-02-29     6
##  4 2020-10-22     6
##  5 2021-02-06     6
##  6 2021-08-14     6
##  7 2023-07-11     6
##  8 2019-06-28     5
##  9 2020-01-24     5
## 10 2020-10-21     5
## # ℹ 36 more rows

There have been 46 episodes of PM10 pollution registered since 2018. If we count episodes by month we have:

pm10_episodes |>
  mutate(month = month(date)) |>
  mutate(month = factor(month)) |>
  ggplot(aes(month)) +
  geom_bar() +
  theme_minimal() +
  labs(x = NULL, y = NULL, title = "Episodes of PM10 Pollution in Barcelona (2018-2025)")

We observe that the highest value of pollution episodes is during June, and the lowest in March and April.

Reading and Tidying Data from Open Data Portals

Although open data portals are supposed to provide data in a structured and reusable way, using this kind of data may require extensive tidying and cleaning, pretty much like any other dataset. Turning a dataset into R tidy data can require some effort, but the resulting dataset can be very useful for exploratory data analysis jobs.

References

All websites checked on 21 July 2025.

Session Info

## R version 4.5.1 (2025-06-13)
## Platform: x86_64-pc-linux-gnu
## Running under: Linux Mint 21.1
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0  LAPACK version 3.10.0
## 
## locale:
##  [1] LC_CTYPE=es_ES.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=es_ES.UTF-8        LC_COLLATE=es_ES.UTF-8    
##  [5] LC_MONETARY=es_ES.UTF-8    LC_MESSAGES=es_ES.UTF-8   
##  [7] LC_PAPER=es_ES.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=es_ES.UTF-8 LC_IDENTIFICATION=C       
## 
## time zone: Europe/Madrid
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] ckanr_0.7.0     DBI_1.2.3       janitor_2.2.1   lubridate_1.9.4
##  [5] forcats_1.0.0   stringr_1.5.1   dplyr_1.1.4     purrr_1.0.4    
##  [9] readr_2.1.5     tidyr_1.3.1     tibble_3.2.1    ggplot2_3.5.2  
## [13] tidyverse_2.0.0
## 
## loaded via a namespace (and not attached):
##  [1] utf8_1.2.4        sass_0.4.10       generics_0.1.3    blogdown_1.21    
##  [5] stringi_1.8.7     httpcode_0.3.0    hms_1.1.3         digest_0.6.37    
##  [9] magrittr_2.0.3    evaluate_1.0.3    grid_4.5.1        timechange_0.3.0 
## [13] bookdown_0.43     fastmap_1.2.0     jsonlite_2.0.0    crul_1.5.0       
## [17] urltools_1.7.3.1  scales_1.3.0      jquerylib_0.1.4   cli_3.6.4        
## [21] crayon_1.5.3      rlang_1.1.6       triebeard_0.4.1   dbplyr_2.5.0     
## [25] bit64_4.6.0-1     munsell_0.5.1     withr_3.0.2       cachem_1.1.0     
## [29] yaml_2.3.10       parallel_4.5.1    tools_4.5.1       tzdb_0.5.0       
## [33] colorspace_2.1-1  curl_6.2.2        vctrs_0.6.5       R6_2.6.1         
## [37] lifecycle_1.0.4   snakecase_0.11.1  bit_4.6.0         vroom_1.6.5      
## [41] pkgconfig_2.0.3   pillar_1.10.2     bslib_0.9.0       gtable_0.3.6     
## [45] Rcpp_1.0.14       glue_1.8.0        xfun_0.52         tidyselect_1.2.1 
## [49] rstudioapi_0.17.1 knitr_1.50        farver_2.1.2      htmltools_0.5.8.1
## [53] labeling_0.4.3    rmarkdown_2.29    compiler_4.5.1