Interroga CSV direttamente con DuckDB

Dec 29 2022
Ti è stato assegnato uno dei seguenti compiti: — caricare un nuovo file csv in BigQuery per l'analisi — aggiungere un nuovo file alla tua pipeline di dati — eseguire alcuni leggeri controlli sulla qualità dei dati su un file-drop di un fornitore Raggiungi il più vicino e gli strumenti più familiari a te noti. Di solito è caricare tutto in Excel, giusto? Che ti fa andare avanti.
duckdb e csv

Ti è stato affidato uno dei seguenti compiti:
— caricare un nuovo file csv in BigQuery per l'analisi
— aggiungere un nuovo file alla tua pipeline di dati
— eseguire alcuni leggeri controlli sulla qualità dei dati su un file-drop di un fornitore

Raggiungi gli strumenti più vicini e familiari a te noti. Di solito è caricare tutto in Excel, giusto? Che ti fa andare avanti. Ma il file è lungo 600 MB e oltre 1,2 milioni di righe. Excel ti dice che può caricare il file solo parzialmente.

Ok, quindi cosa succederà dopo?

Potresti essere su GCP/BigQuery, quindi fai il clicky-and-droppy ma BQ ti dice che la posizione 1023845 non va bene. Come fai a trovare quella posizione di byte in un file? <sospiro>

Cerchi StackOverflow e ti dicono di usare i panda. Ti porta fino in fondo, ma la tua velocità è ostacolata perché hai dimenticato ogni comando. Forse usi ChatGPT, ma hai bisogno di risposte subito e ne hai bisogno velocemente.

Non sarebbe bello semplicemente `selezionare * da output.csv`?

Beh, puoi assolutamente.

Passo 1

brew install duckdb

> duckdb
D> select * from ‘output.csv*’

Puoi anche fare `data/*.csv`, o anche altre estensioni come `data/*.parquet`.

Risoluzione dei problemi

Quindi il caricamento csv non sta andando così bene. Hai iniziato con duckdb, dice


Error: Invalid Input Error: Could not convert string ‘Column_1’ to INT32 
in column “Column_1”, at line 100002.

La prima cosa che dovremmo fare è creare una vista sopra il tuo csv con alcuni numeri di riga in modo da poter iniziare a verificare il file e fare alcuni controlli di qualità leggeri.


create sequence seq_id start 1;

D> create or replace view test_1 as SELECT nextval(‘seq_id’) as seq_id, * 
from read_csv(‘output.csv’, ALL_VARCHAR=1, AUTO_DETECT=TRUE);

couple of things here, of reference is https://duckdb.org/docs/data/csv

  • Hai dei dati errati. Duckdb campiona ogni 100 righe e indovina il tipo di colonna. Alcuni dati nella tua colonna non sono come dovrebbero essere. `ALL_VARCHAR` ti consente di caricare tutto, indipendentemente dal tipo per l'analisi
    — `AUTO_DETECT` significa usare la prima riga, indovina quante colonne dovrebbero esistere. Altrimenti dovremmo digitarli manualmente, `columns={'Column_1,', 'Column_2…}'`

A questo punto, poiché la nostra sequenza conta sempre, è un buon momento per bloccarla e materializzare la vista con i nostri numeri di riga.


create table test_1_mv as (select * from test_1);


 — it seems that line numbers in errors are zero-indexed
 — however you cannot start a sequence from 0
 — so we need to subtract `1` from the id
select * from test_1 where seq_id = 100001
┌────────┬───────────────┬──────────────┬──┐
│ seq_id │ Column_1      │ Column_2     │  │
│ int64  │ varchar       │ varchar      │  │
├────────┼───────────────┼──────────────┼──┤
│ 100001 │ Column_1_text │ Column_2_text│  │
├────────┴───────────────┴──────────────┴──┤
│ 1 rows                                   │
└──────────────────────────────────────────┘

Troviamo tutte le righe incriminate. Il mio primo pensiero è cercare tutte le righe che contengono `Column_1_text`.


select * from test_1 where column_1 = ‘Column_1_text’;


select * from test_1
where regexp_matches(Column_1, ‘[a-zA-Z]’)


delete from test_1_mv where seq_id in (select seq_id from test_1_mv 
where regexp_matches(Column_1, ‘[a-zA-Z]’));

Scrivere il nuovo file — Esporta

Per esportare i dati da una tabella in un file CSV, utilizzare l'istruzione `COPY`.


COPY test_1_mv TO ‘output_cleaned.csv’ (HEADER, DELIMITER ‘,’);