initial repository creation

This commit is contained in:
putro 2020-04-05 19:21:02 +02:00
commit 62d0803379
4 changed files with 181 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
stazioni.csv

34
README Normal file
View File

@ -0,0 +1,34 @@
Software per il recupero delle informazioni dei dati dei sensori ambientali pubblicati dall'arpa sul portale opendata della regione lombardia
la lista delle stazioni e dai sensori si trova qui':
https://www.dati.lombardia.it/Ambiente/Stazioni-qualit-dell-aria/ib47-atvt
lo script stazioni.py stampa la lista delle stazioni e dei sensori recuperando i dati da link qui' sopra,
se si salva invece il contenuto di quel link come stazioni.csv la ricerca viene fatta offline in questo file.
il portale contiene due tipi di documenti: i dataset e i files.
i dataset esistono solo dal 2017 in avanti, sono annuali, e non contengono i dati dei sensori che ad oggi risultano non piu' attivi,
(ad es. per un sensore che ha smesso di funzionare nel 2018 non sono piu' disponibili i dati del 2017).
Sono interrogabili da remoto richiedendo solo i dati di sensori specifici, senza necessita' di scaricare tutto il dataset.
I files invece sono disponibilli in formato csv (non compressi o zippati), la lista attuale e' questa:
sensori_aria_1968-1995.zip - 47M
sensori_aria_1996-2000.zip - 67M
sensori_aria_2001-2004.zip - 70M
sensori_aria_2005-2007.zip - 62M
sensori_aria_2008-2010.zip - 69M
sensori_aria_2011.zip - 24M
sensori_aria_2012.zip - 23M
sensori_aria_2013.zip - 23M
sensori_aria_2014.zip - 21M
sensori_aria_2015.zip - 21M
sensori_aria_2016.zip - 21M
sensori_aria_2017.zip - 13M
sensori_aria_2018.zip - 13M
sensori_aria_2019.zip - 13M
per visualizzarne i dati e' necessario scaricare l'intero file e processarlo.
Quindi per l'analisi dei dati recenti e' piu' comodo lavorare con i dataset, per analisi storiche invece bisogna usare i csv
openlamb usa i dataset,
in futuro ci sara' una versione che lavorera' con i csv

106
openlamb.py Executable file
View File

@ -0,0 +1,106 @@
#!/usr/bin/env python
# pylint: skip-file
import argparse
import traceback
import sys
import subprocess
import pandas as pd
import numpy as np
from sodapy import Socrata
import matplotlib.pyplot as plt
datasets_ambiente = {"2020": "nicp-bhqi",
"2019": "kujm-kavy",
"2018": "bgqm-yq56",
"2017": "j8j8-qsb2"}
def _connect():
client = Socrata("www.dati.lombardia.it", None)
return client
def process_dataset(dataset, sensore):
client = _connect()
results = client.get(dataset, IdSensore=sensore)
results_df = pd.DataFrame.from_records(results)
try:
results_df = results_df.astype({'valore': 'float64'})
except:
print('\nspiacente, dati non disponibili per il sensore %s') % sensore
sys.exit(-1)
results_df["data"] = pd.to_datetime(results_df["data"])
results_df = results_df.replace(-9999, np.nan)
results_df.sort_values(by=['data'], inplace=True)
results_df.rename(columns = {'valore':sensore}, inplace = True)
results_df.drop(columns=['idoperatore', 'idsensore', 'stato'], inplace = True)
return results_df
def merge_df(dataframes, sensori):
df = dataframes[sensori[0]]
for sensore in sensori[1:]:
df = pd.merge(df, dataframes[sensore])
return df
def get_dataframes(datasets, sensori):
dataframes = {}
for sensore in sensori:
df = process_dataset(datasets[0], sensore)
for dataset in datasets[1:]:
df = pd.concat([df, process_dataset(dataset, sensore)], axis=0)
dataframes[sensore] = df
return dataframes
def plot_dataframe(dataframe):
dataframe.plot(x='data')
plt.axhline(y=50, color='black', linestyle='-', label='24-hour average EU limit')
plt.show()
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--dataset", nargs='+', required=True, help="ricerca dei datasets")
parser.add_argument('--sensori', nargs='+', required=True, help="specifica i sensori")
args = parser.parse_args()
try:
datasets = []
if "all" in args.dataset:
for k in datasets_ambiente.keys():
datasets.append(datasets_ambiente[k])
else:
for d in args.dataset:
datasets.append(datasets_ambiente[d])
sensori = args.sensori
dataframes = get_dataframes(datasets, sensori)
datamerged = merge_df(dataframes, sensori)
import stazioni
s = stazioni.get_stazioni()
for sensore in sensori:
location = s.loc[s['idsensore'] == sensore, 'nomestazione'].iloc[0]
print('Valore medio per il sensore %s %s: %s' % (sensore, location, datamerged[sensore].mean().round(1)))
plot_dataframe(datamerged)
except KeyError:
print("\nErrore:")
#print("Datasets disponibili:")
#print('\n'.join([str(lst) for lst in sorted(datasets_ambiente.keys())]))
traceback.print_exc()
except KeyboardInterrupt:
print("program terminated by user")
except SystemExit:
print("program terminated, bye")
except:
print("\nAn unhandled exception occured, here's the traceback!\n")
traceback.print_exc()
print("\nReport this to putro@autistici.org")
sys.exit()
if __name__ == '__main__':
main()

40
stazioni.py Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env python
# pylint: skip-file
import os.path
import pandas as pd
from sodapy import Socrata
def _connect():
client = Socrata("www.dati.lombardia.it", None)
return client
def get_stazioni(offline=False):
if offline:
stazioni = pd.read_csv("stazioni.csv")
stazioni_df = pd.DataFrame.from_records(stazioni)
stazioni_df.drop(columns=["Storico", "Idstazione", "Utm_Nord", "UTM_Est", "lat", "lng", "location", "Limiti amministrativi 2014 delle province di Regione Lombardia", "Limiti amministrativi 2015 delle province di Regione Lombardia"], inplace=True)
stazioni_df.columns = [x.lower() for x in stazioni_df.columns]
else:
client = _connect()
stazioni = client.get("ib47-atvt")
stazioni_df = pd.DataFrame.from_records(stazioni)
stazioni_df.drop(columns=[":@computed_region_6hky_swhk", ":@computed_region_ttgh_9sm5", "utm_est", "utm_nord", "storico", "idstazione", "lat", "lng", "location"], inplace=True)
stazioni_df["datastart"] = pd.to_datetime(stazioni_df["datastart"])
stazioni_df["datastop"] = pd.to_datetime(stazioni_df["datastop"])
return stazioni_df
def print_stazioni():
pd.set_option('display.max_rows', None)
if os.path.exists("stazioni.csv"):
stazioni = get_stazioni(offline=True)
else:
stazioni = get_stazioni()
print(stazioni)
if __name__ == '__main__':
print_stazioni()