Consultar CSV diretamente com DuckDB

Dec 29 2022
Você recebeu uma das seguintes tarefas: — carregar um novo arquivo csv no BigQuery para análise — adicionar um novo arquivo ao seu pipeline de dados — fazer algumas verificações de qualidade de dados de toque leve em um arquivo de fornecedores dropar Você alcança o mais próximo e ferramentas mais familiares conhecidas por você. Normalmente é para carregar tudo no Excel, né? O que faz você continuar.
duckdb e csv

Você recebeu uma das seguintes tarefas:
— carregar um novo arquivo csv no BigQuery para análise
— adicionar um novo arquivo ao seu pipeline de dados
— fazer algumas verificações de qualidade de dados leves em um arquivo drop de fornecedores

Você busca o ferramental mais próximo e familiar conhecido por você. Normalmente é para carregar tudo no Excel, né? O que faz você continuar. Mas o arquivo tem 600 MB e mais de 1,2 milhão de linhas. O Excel informa que só pode carregar o arquivo parcialmente.

Ok, então o que vem a seguir?

Você pode estar no GCP/BigQuery, então clica e solta, mas o BQ diz que a posição 1023845 não é boa. Como você encontra essa posição de byte em um arquivo? <suspiro>

Você pesquisa no Stackoverflow e eles dizem para você usar pandas. Ele leva você até lá, mas sua velocidade é prejudicada porque você esqueceu todos os comandos. Talvez você use o ChatGPT, mas precisa de respostas imediatamente e rapidamente.

Não seria legal apenas `selecionar * de output.csv`?

Bem, você pode totalmente.

Passo 1

brew install duckdb

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

Você pode até fazer `data/*.csv`, ou até mesmo outras extensões como `data/*.parquet`.

Solução de problemas

Portanto, a carga do csv não está indo tão bem. Você começou com duckdb, ele diz


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

A primeira coisa que devemos fazer é criar uma exibição em cima do seu csv com alguns números de linha para que você possa começar a verificar o arquivo e fazer algumas verificações de qualidade de toque leve.


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

  • Você tem alguns dados ruins. O Duckdb faz amostras a cada 100 linhas e adivinha o tipo de coluna. Alguns dados em sua coluna não são o que deveriam ser. `ALL_VARCHAR` permite que você carregue tudo, independentemente do tipo de análise
    — `AUTO_DETECT` significa usar a primeira linha, adivinhar quantas colunas devem existir. Caso contrário, teríamos que digitá-los manualmente, `columns={'Column_1,', 'Column_2…}'`

Neste ponto, como nossa sequência está sempre contando, é um bom momento para bloqueá-la e materializar a exibição com nossos números de linha.


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                                   │
└──────────────────────────────────────────┘

Vamos encontrar todas as linhas ofensivas. Meu primeiro pensamento é procurar todas as linhas que tenham `Column_1_text` nelas.


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]’));

Escrevendo o novo arquivo — Exportar

Para exportar os dados de uma tabela para um arquivo CSV, use a instrução `COPY`.


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