Filtrare un file CSV da 24 milioni di righe in pochi secondi

XSV una utility a riga di comando dalle caratteristiche sorprendenti

Andrea Borruso
mai più senza
3 min readOct 5, 2020

--

Un file di testo — un CSV — da 1.4 GB, come questo da 24 milioni di righe disponibile sul sito “Humanitarian Data Exchange” non è facile da gestire, specie in modo diretto.

È un formato “piatto”, senza indici (che ne renderebbero molto più rapida la lettura), senza tipi di campi definiti (è tutto “testo” e si perdono i vantaggi di funzioni basate ad esempio su numeri o date) e che in questo caso — per le sue dimensioni — non è possibile aprire con un foglio elettronico e pressoché con tutti gli strumenti “visuali”.
Non è per questa ragione di solito un formato di “lavoro”, ma un formato di scambio.

Non stiamo parlato di “big data”, ma sicuramente di dati “grossi”, che richiedono strumenti adeguati alla loro “taglia”; da installare, configurare e studiare (vale sempre). Alcuni di questi in particolare hanno una certa complessità e spesso richiedono un sysadmin accanto.
Ma nel mondo delle utility a riga di comando, ci sono alcuni strumenti che “lasciano di stucco”, che fanno poche cose, ma benissimo.

Una di queste è la straordinaria XSV, un’applicazione open source disponibile per tutti i sistemi operativi, scritta in Rust.

Come applicare un filtro basato sul valore dei campi

Il file di input ha una struttura come quella sottostante: tre campi numerici (latitudine, longitudine e popolazione), per descrivere la distribuzione della popolazione in Italia.

Lat,Lon,Population
45.581527,11.4851388,5.12417
44.414861,8.95513,39.9738108
45.5634722,9.674861,0.0
40.52763,15.484027,0.0
45.705972,13.73013,1.924541
...,...,...

XSV ha il comando search, che applica a un singolo campo un filtro basato su espressioni regolari. Quindi accidenti non posso applicare una query (alla SQL) come “tutti i record in cui la Lon è compresa tra 15.6 e 17.25, la Lat tra 37.9 e 40.15 e la popolazione diversa da 0.0”?
È vero, non posso filtrare usando funzioni numeriche ( <,>, ecc.), ma posso scrivere una regex che fa qualcosa di analogo sulle stringhe e che mi dà un output in circa 4 secondi.

La sintassi del comando è quella di sotto (qui in copia):

xsv search -s Lat '(^37\.9.*$|3[8-9]\..*$|^40\.0.*$|^40\.1[0-4].*$|^40\.150*$)' population_ita_2019-07-01.csv | \
xsv search -s Lon '(^15\.[6-9].*$|^16\..*$|^17\.[0-1].*$|^17\.2[0-4]$|^17\.25[0]*$)' | \
xsv search -s Population '[^0.0]' >output.csv

Ovvero:

  • si inizia dal filtrare per latitudine, con il comando search, impostando poi il campo su cui farlo e la sintassi dell’espressione regolare;
  • il risultato di questo primo filtro, viene di nuovo sottoposto a un altro, ma basato sulla longitudine;
  • poi il risultato viene ancora una volta filtrato, ma per popolazione;
  • e infine viene salvato tutto su file.

Qui è possibile vedere un esempio di come funziona il filtro tramite espressione regolare sulla latitudine (grazie ad Andrea Giudiceandrea per avermi fatto notare che la mia regex originaria non era “stringente” rispetto all'esempio proposto).

XSV mi restituisce un output in pochi secondi (ho un PC con 16 GB di RAM e processore i7), senza avere attivato nulla di parallelo, su processori e/o PC.

XSV fa molto di più e ha tanti altri comandi. Si installa come indicato qui; il modo forse più comodo per farlo è quello di scaricare l’eseguibile compresso per il proprio sistema operativo, decomprimerlo, spostarlo in una cartella del PATH del proprio sistema e renderlo eseguibile.

--

--

Andrea Borruso
mai più senza

#data #maps #GIS #baci #condivisione. Orgoglioso di essere presidente di @ondatait