Запрос CSV напрямую с DuckDB

Dec 29 2022
Вам было поручено выполнить одно из следующих действий: — загрузить новый CSV-файл в BigQuery для анализа — добавить новый файл в конвейер данных — провести легкую проверку качества данных в файле поставщика. и самые знакомые инструменты, известные вам. Обычно нужно загрузить все это в Excel, верно? Что вас заводит.
уткабд и CSV

Вам было поручено выполнить одно из следующих действий:
— загрузить новый CSV-файл в BigQuery для анализа
— добавить новый файл в конвейер данных
— выполнить легкую проверку качества данных в файле поставщика

Вы тянетесь к самому близкому и знакомому инструменту, известному вам. Обычно нужно загрузить все это в Excel, верно? Что вас заводит. Но файл имеет размер 600 МБ и более 1,2 млн строк. Excel сообщает, что может загрузить файл только частично.

Хорошо, так что дальше?

Вы можете быть на GCP/BigQuery, поэтому вы делаете клики и капли, но BQ говорит вам, что позиция 1023845 не годится. Как вообще найти эту позицию байта в файле? <вздох>

Вы ищете Stackoverflow, и они говорят вам использовать pandas. Он доводит вас до конца, но ваша скорость снижается, потому что вы забыли все команды. Возможно, вы используете ChatGPT, но вам нужны ответы сразу, и они нужны вам быстро.

Было бы здорово просто `выбрать * из output.csv`?

Ну вполне можешь.

Шаг 1

brew install duckdb

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

Вы даже можете сделать `data/*.csv` или даже другие расширения, такие как `data/*.parquet`.

Поиск неисправностей

Таким образом, загрузка csv идет не так хорошо. Вы начали с DuckDB, он говорит


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

Первое, что мы должны сделать, это создать представление поверх вашего csv с некоторыми номерами строк, чтобы вы могли начать проверку файла и выполнить некоторые проверки качества.


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

  • У вас неверные данные. Duckdb производит выборку каждые 100 строк и угадывает тип столбца. Некоторые данные в вашем столбце не такие, какими должны быть. ALL_VARCHAR позволяет вам загрузить все это, независимо от типа для анализа
    — AUTO_DETECT означает использование первой строки, угадать, сколько столбцов должно существовать. В противном случае нам пришлось бы вводить их вручную, `columns={'Column_1,', 'Column_2…}'`

На этом этапе, поскольку наша последовательность всегда подсчитывается, самое время заблокировать ее и материализовать представление с нашими номерами строк.


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

Давайте найдем все оскорбительные строки. Моя первая мысль — найти все строки, в которых есть «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]’));

Запись нового файла — Экспорт

Чтобы экспортировать данные из таблицы в файл CSV, используйте оператор COPY.


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