updated openlamb to read data online or from csv files

master
putro 2020-04-12 14:08:38 +02:00
parent a792294d4c
commit df4010a2cf
2 changed files with 105 additions and 43 deletions

18
README
View File

@ -1,6 +1,6 @@
Software per il recupero delle informazioni dei dati dei sensori ambientali pubblicati dall'arpa sul portale opendata della regione lombardia 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': la lista delle stazioni e dai sensori si trova qui':
https://www.dati.lombardia.it/Ambiente/Stazioni-qualit-dell-aria/ib47-atvt 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, 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. se si salva invece il contenuto di quel link come stazioni.csv la ricerca viene fatta offline in questo file.
@ -26,9 +26,19 @@ sensori_aria_2017.zip - 13M
sensori_aria_2018.zip - 13M sensori_aria_2018.zip - 13M
sensori_aria_2019.zip - 13M sensori_aria_2019.zip - 13M
per visualizzarne i dati e' necessario scaricare l'intero file e processarlo. per visualizzarne i dati e' necessario scaricare l'intero file.
Quindi per l'analisi dei dati recenti e' piu' comodo lavorare con i dataset, per analisi storiche invece bisogna usare i csv 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, i csv vanno scaricati manualmente (per ora) e messi nella cartella csv o in una cartella a scelta modificando il percorso specificato nel file openlamb.py
in futuro ci sara' una versione che lavorera' con i csv
sintassi:
python openlamb.py --dataset 2018 2019 --sensori 6956 10320
mostra i grafico per il dataset degli anni 2018 e 2019 per i sensori indicati
python openlamb.py --csv 2018.csv 2019.csv --sensori 6956 10320
mostra i grafico dei dati contenuti nei file 2018.csv e 2019.csv per i sensori indicati
python openlamb.py --dataset 2019 --csv 2019.csv --sensori 6956
mostra il grafico del confronto dei dati nel dataset e nel file csv per il sensore indicato

View File

@ -1,19 +1,21 @@
#!/usr/bin/env python #!/usr/bin/env python
# pylint: skip-file
import argparse import argparse
import traceback import traceback
import sys import sys
import subprocess
import pandas as pd import pandas as pd
import numpy as np import numpy as np
from sodapy import Socrata from sodapy import Socrata
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import glob
import os
from os import getcwd, chdir
path_to_csv_files = "csv/"
datasets_ambiente = {"2020": "nicp-bhqi", datasets_ambiente = {"2020": "nicp-bhqi",
"2019": "kujm-kavy", "2019": "kujm-kavy",
"2018": "bgqm-yq56", "2018": "bgqm-yq56",
"2017": "j8j8-qsb2"} "2017": "j8j8-qsb2"}
@ -21,77 +23,126 @@ def _connect():
client = Socrata("www.dati.lombardia.it", None) client = Socrata("www.dati.lombardia.it", None)
return client return client
def process_dataset(dataset, sensore):
def read_data_online(dataset, sensore):
client = _connect() client = _connect()
results = client.get(dataset, IdSensore=sensore) return client.get(dataset, IdSensore=sensore)
def read_data_from_csv(datafile):
return pd.read_csv("csv/" + datafile, usecols=['IdSensore', 'Data', 'Valore', 'Stato', 'idOperatore'])
def process(dati, sensore, csv):
""" processa i dati per un sensore da un dataset o un file csv e restituisce un dataframe """
print('Sto processando i dati del sensore %s per l\'origine dati %s...' % (sensore, dati))
if csv:
results = read_data_from_csv(dati)
else:
results = read_data_online(dati, sensore)
results_df = pd.DataFrame.from_records(results) results_df = pd.DataFrame.from_records(results)
results_df.columns = [x.lower() for x in results_df.columns]
try: try:
results_df = results_df.astype({'idsensore': 'int64'})
results_df = results_df[results_df['idsensore'] == int(sensore)]
results_df = results_df.astype({'valore': 'float64'}) results_df = results_df.astype({'valore': 'float64'})
results_df["data"] = pd.to_datetime(results_df["data"])
results_df = results_df.replace(-9999, np.nan)
except: except:
print('\nspiacente, dati non disponibili per il sensore %s') % sensore print('\nERRORE: dati non disponibili per il sensore %s\n') % sensore
traceback.print_exc()
sys.exit(-1) 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.sort_values(by=['data'], inplace=True)
results_df.rename(columns = {'valore':sensore}, inplace = True) results_df.rename(columns={'valore': sensore}, inplace=True)
results_df.drop(columns=['idoperatore', 'idsensore', 'stato'], inplace = True) results_df.drop(columns=['idoperatore', 'idsensore', 'stato'],
inplace=True)
return results_df return results_df
def merge_df(dataframes, sensori): def merge_df(dataframes, sensori):
""" fonde diversi dataframes in un dataframe unico con un sensore per colonna """
df = dataframes[sensori[0]] df = dataframes[sensori[0]]
for sensore in sensori[1:]: for sensore in sensori[1:]:
df = pd.merge(df, dataframes[sensore]) df = pd.merge(df, dataframes[sensore])
return df return df
def get_dataframes(datasets, sensori): def get_dataframes(dati_csv, dati, sensori):
""" salva in un dict i dataframes dei vari sensori richiesti """
dataframes = {} dataframes = {}
for sensore in sensori: for sensore in sensori:
df = process_dataset(datasets[0], sensore) if dati_csv:
for dataset in datasets[1:]: df = process(dati_csv[0], sensore, True)
df = pd.concat([df, process_dataset(dataset, sensore)], axis=0) for d in dati_csv[1:]:
dataframes[sensore] = df df = pd.concat([df, process(d, sensore, True)], axis=0)
df.rename(columns={sensore: sensore + "-csv"}, inplace=True)
dataframes[sensore + "-csv"] = df
if dati:
df = process(dati[0], sensore, False)
for d in dati[1:]:
df = pd.concat([df, process(d, sensore, False)], axis=0)
dataframes[sensore] = df
return dataframes return dataframes
def plot_dataframe(dataframe): def plot_dataframe(dataframe):
dataframe.plot(x='data') dataframe.plot(x='data')
plt.axhline(y=50, color='black', linestyle='-', label='24-hour average EU limit') plt.axhline(y=50, color='black', linestyle='-', label='EU limit')
plt.show() plt.show()
def main(): def list_of_csv_files(dir_name):
saved = getcwd()
os.chdir(dir_name)
filelist = glob.glob('*.csv')
chdir(saved)
return filelist
def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("--dataset", nargs='+', required=True, help="ricerca dei datasets") parser.add_argument("--dataset", nargs='+', required=False,
parser.add_argument('--sensori', nargs='+', required=True, help="specifica i sensori") help="ricerca dei datasets")
parser.add_argument("--csv", nargs='+', required=False,
help="ricerca nei files csv")
parser.add_argument('--sensori', nargs='+', required=True,
help="cerca i dati di questi sensori")
args = parser.parse_args() args = parser.parse_args()
try: try:
datasets = [] dati_csv = []
if "all" in args.dataset: csv_files = list_of_csv_files(path_to_csv_files)
for k in datasets_ambiente.keys(): if args.csv:
datasets.append(datasets_ambiente[k]) if "all" in args.csv:
else: dati_csv = csv_files
for d in args.dataset: else:
datasets.append(datasets_ambiente[d]) for d in args.csv:
sensori = args.sensori if d in csv_files:
dataframes = get_dataframes(datasets, sensori) dati_csv.append(d)
datamerged = merge_df(dataframes, sensori) else:
print("spiacente, ma il file csv %s non e' disponibile nel "
"percorso indicato: %s" % (d, path_to_csv_files))
sys.exit(-1)
dati = []
if args.dataset:
if "all" in args.dataset:
for k in datasets_ambiente.keys():
dati.append(datasets_ambiente[k])
else:
for d in args.dataset:
dati.append(datasets_ambiente[d])
dataframes = get_dataframes(dati_csv, dati, args.sensori)
datamerged = merge_df(dataframes, dataframes.keys())
import stazioni import stazioni
s = stazioni.get_stazioni() s = stazioni.get_stazioni()
for sensore in sensori: for sensore in datamerged.columns[1:]:
location = s.loc[s['idsensore'] == sensore, 'nomestazione'].iloc[0] print(sensore)
location = s.loc[s['idsensore'] == sensore.split("-")[0], 'nomestazione'].iloc[0]
print('Valore medio per il sensore %s %s: %s' % (sensore, location, datamerged[sensore].mean().round(1))) print('Valore medio per il sensore %s %s: %s' % (sensore, location, datamerged[sensore].mean().round(1)))
plot_dataframe(datamerged) plot_dataframe(datamerged)
except KeyError: except KeyError:
print("\nErrore:") print("\nKeyError: forse hai specificato un dataset che non esiste ?")
#print("Datasets disponibili:") traceback.print_exc()
#print('\n'.join([str(lst) for lst in sorted(datasets_ambiente.keys())]))
traceback.print_exc()
except KeyboardInterrupt: except KeyboardInterrupt:
print("program terminated by user") print("program terminated by user")
except SystemExit: except SystemExit:
@ -102,5 +153,6 @@ def main():
print("\nReport this to putro@autistici.org") print("\nReport this to putro@autistici.org")
sys.exit() sys.exit()
if __name__ == '__main__': if __name__ == '__main__':
main() main()