Consulta CSV directamente con DuckDB

Dec 29 2022
Se le asignó una de las siguientes tareas: — cargue un nuevo archivo csv en BigQuery para su análisis — agregue un nuevo archivo a su canalización de datos — realice algunas verificaciones de calidad de datos de toque ligero en un archivo de proveedores y la mayoría de las herramientas conocidas por usted. Por lo general, es para cargarlo todo en Excel, ¿verdad? Lo que te pone en marcha.
patodb y csv

Se le asignó una de las siguientes tareas:
— cargue un nuevo archivo csv en BigQuery para su análisis
— agregue un nuevo archivo a su flujo de datos
— realice algunas verificaciones de calidad de datos de toque ligero en un archivo de proveedores

Alcanza las herramientas más cercanas y familiares que conoce. Por lo general, es para cargarlo todo en Excel, ¿verdad? Lo que te pone en marcha. Pero el archivo tiene 600 MB y más de 1,2 millones de líneas. Excel le dice que solo puede cargar el archivo parcialmente.

Bien, entonces, ¿qué sigue?

Es posible que esté en GCP/BigQuery, por lo que hace clic y droppy, pero BQ le dice que la posición 1023845 no es buena. ¿Cómo encuentras esa posición de byte en un archivo? <suspiro>

Buscas en Stackoverflow y te dicen que uses pandas. Te lleva hasta allí, pero tu velocidad se ve obstaculizada porque has olvidado todos los comandos. Tal vez use ChatGPT, pero necesita respuestas de inmediato, y las necesita rápido.

¿No sería genial simplemente 'seleccionar * de salida.csv'?

Bueno, totalmente puedes.

Paso 1

brew install duckdb

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

Incluso puede hacer `data/*.csv`, o incluso otras extensiones como `data/*.parquet`.

Solución de problemas

Entonces la carga de csv no va tan bien. Has empezado con duckdb, dice


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

Lo primero que debemos hacer es crear una vista en la parte superior de su csv con algunos números de línea para que pueda comenzar a verificar el archivo y realizar algunos controles de calidad de toque ligero.


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

  • Tienes algunos datos malos. Duckdb muestrea cada 100 líneas y adivina el tipo de columna. Algunos datos en su columna no son lo que se supone que deben ser. `ALL_VARCHAR` le permite cargarlo todo, independientemente del tipo de análisis
    : `AUTO_DETECT` significa usar la primera fila, adivine cuántas columnas deberían existir. De lo contrario, tendríamos que escribirlas manualmente, `columns={'Column_1,', 'Column_2…}'`

En este punto, dado que nuestra secuencia siempre cuenta, es un buen momento para bloquearla y materializar la vista con nuestros números de línea.


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

Encontremos todas las filas ofensivas. Mi primer pensamiento es buscar todas las filas que tengan `Column_1_text` en ellas.


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

Escribiendo el nuevo archivo — Exportar

Para exportar los datos de una tabla a un archivo CSV, use la instrucción `COPY`.


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