DuckDB InvalidInputException при подсчете строк через PyArrow

Вопрос или проблема

Я использую DuckDB и PyArrow для анализа набора данных такси NYC, доступного по адресу s3://ursa-labs-taxi-data, как описано здесь.

Это набор данных объемом 37 ГБ о поездах такси NYC с января 2009 года по июнь 2019 года, организованный следующим образом:

├───2009
│   ├───01
│   │   └── data.parquet
│   ├───02
│   │   └── data.parquet
│   ├───03
│   │   └── data.parquet
...
├───2019
│   ├───04
│   │   └── data.parquet
│   ├───05
│   │   └── data.parquet
│   ├───06
│   │   └── data.parquet

┌────────────────────┬─────────────┬──────────┐
│    column_name     │ column_type │  null    │
│      varchar       │   varchar   │ varchar  │
├────────────────────┼─────────────┼──────────┤
│ vendor_id          │ VARCHAR     │ YES      │
│ pickup_at          │ TIMESTAMP   │ YES      │
│ dropoff_at         │ TIMESTAMP   │ YES      │
│ passenger_count    │ TINYINT     │ YES      │
│ trip_distance      │ FLOAT       │ YES      │
│ pickup_longitude   │ FLOAT       │ YES      │
│ pickup_latitude    │ FLOAT       │ YES      │
│ rate_code_id       │ INTEGER     │ YES      │
│ store_and_fwd_flag │ VARCHAR     │ YES      │
│ dropoff_longitude  │ FLOAT       │ YES      │
│ dropoff_latitude   │ FLOAT       │ YES      │
│ payment_type       │ VARCHAR     │ YES      │
│ fare_amount        │ FLOAT       │ YES      │
│ extra              │ FLOAT       │ YES      │
│ mta_tax            │ FLOAT       │ YES      │
│ tip_amount         │ FLOAT       │ YES      │
│ tolls_amount       │ FLOAT       │ YES      │
│ total_amount       │ FLOAT       │ YES      │
├────────────────────┴─────────────┴──────────┘

Мой код на Python выглядит следующим образом:

import duckdb
import pyarrow.dataset as ds
import time

nyc_dataset = ds.dataset('C:\\data\\nyc-taxi\\', partitioning=["year", "month"])
con = duckdb.connect()

start = time.time()
query = con.execute("select count(*) from nyc_dataset") # *** запрос ***
results = query.fetchall()
end = time.time()

for x in results:
    print(x)
print()
print(f'[Запрос занял {end - start:.2f}с]')

Это вызывает ошибку:

> python duckdb-arrow.py
Traceback (most recent call last):
  File "D:\Storage\Code\untracked\duck-arrow\nyc-arrow2.py", line 9, in <module>
    query = con.execute("select count(*) from nyc_dataset")
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
duckdb.duckdb.InvalidInputException: Invalid Input Error: arrow_scan: get_next failed(): NotImplemented: Unsupported cast from string to null using function cast_null

Однако, если я изменю запрос на select count(*) from nyc_dataset where year > 2008, то все работает. И все же, поскольку набор данных охватывает период с января 2009 года по июнь 2019 года, кажется, что обрабатывается точно такое же количество данных.

> python duckdb-arrow.py
(1547741381,)

[Запрос занял 4.47с]

Странно, но запрос select count(vendor_id) from nyc_dataset также работает и дает тот же результат, хотя выполнение запроса занимает почти 13 секунд.

Я использую Python 3.12.2, и мой виртуальный окружение имеет следующие зависимости:

duckdb==1.1.1
numpy==2.1.2
pyarrow==17.0.0

Я новичок в использовании Arrow с DuckDB, поэтому не понимаю, почему это происходит. Мог бы кто-нибудь указать, что я делаю не так? Спасибо!

Ответ или решение

Решение проблемы InvalidInputException в DuckDB при работе с PyArrow и подсчёте строк

Введение

Используя DuckDB совместно с PyArrow для анализа набора данных такси Нью-Йорка, вы столкнулись с ошибкой InvalidInputException, возникающей при попытке выполнить запрос на подсчёт строк для всего набора данных. Ошибка звучит как: Invalid Input Error: arrow_scan: get_next failed(): NotImplemented: Unsupported cast from string to null using function cast_null. В данном ответе мы рассмотрим возможные причины этой проблемы и способы её решения.

Описание проблемы

Вы работаете с набором данных такси, содержащим 37 ГБ информации, организованной по годам и месяцам, и пытаетесь выполнить следующий запрос:

SELECT COUNT(*) FROM nyc_dataset

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

SELECT COUNT(*) FROM nyc_dataset WHERE year > 2008

или на:

SELECT COUNT(vendor_id) FROM nyc_dataset

запросы выполняются успешно.

Причины возникновения ошибки

  1. Проблемы с типами данных: Ошибка может быть связана с тем, как DuckDB обрабатывает невидимые (null) значения в столбцах. Если в ваших данных имеются строки, не имеющие корректных значений для некоторых колонок, это может вызвать конфликт при попытке выполнить общий подсчёт.

  2. Отсутствие явного указания типов данных: DuckDB может не удачно обрабатывать отсутствие информации о структуре данных при выполнении запроса, требующего полной проверки всех строк.

  3. Версия библиотек: Вы используете версии duckdb==1.1.1, numpy==2.1.2 и pyarrow==17.0.0. Возможно, в более новых версиях этих библиотек были исправлены ошибки, которые могут влиять на возможность работы с null значениями.

Решения

1. Проверка и очистка данных

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

SELECT COUNT(*) FROM nyc_dataset WHERE vendor_id IS NULL;

Это поможет вам узнать, есть ли в ваших данных строки с отсутствующими значениями.

2. Уточнение запроса

Попробуйте более явное указание в запросе, выбирая определённые столбцы, которые явно не содержат null значений. Например:

SELECT COUNT(vendor_id) FROM nyc_dataset;

3. Использование фильтров

Вы уже заметили, что запрос с фильтром WHERE year > 2008 работает. Это может быть временным решением для того, чтобы избежать ошибок. Однако, это может не подходить для всех случаев использования, особенно если вам необходимо учитывать все строки в данных.

4. Обновление библиотек

Рекомендуется обновить библиотеки до самых последних версий:

pip install --upgrade duckdb pyarrow numpy

Проверьте изменения в документации и ведите учёт возможных улучшений процесса обработки данных.

5. Обращение к документации

DuckDB и PyArrow имеют хорошую документацию, которая может содержать информацию о решении аналогичных проблем. Изучите разделы, относящиеся к работе с null значениями и специфическим типам данных.

6. Обработка данных с использованием PyArrow

Попробуйте загрузить данные в PyArrow DataFrame и выполнить операции с ними до того, как они будут загружены в DuckDB. Например:

import pyarrow.parquet as pq

table = pq.read_table('C:\\data\\nyc-taxi\\2009\\01\\data.parquet')
print(table.num_rows)

Это может помочь в идентификации и исправлении потенциальных ошибок в ваших данных до их обработки в DuckDB.

Заключение

Надеемся, что данное руководство поможет вам разобраться с ошибкой InvalidInputException при работе с DuckDB и PyArrow. Проблемы, связанные с типами данных и null значениями, часто требуют внимательного рассмотрения, и использование вышеописанных подходов может существенным образом повысить качество обработки ваших данных. Если проблема сохраняется и после выполнения всех рекомендаций, советуем обратиться непосредственно в службу поддержки DuckDB или искать помощь в сообществах разработчиков.

Оцените материал
Добавить комментарий

Капча загружается...