- Вопрос или проблема
- Ответ или решение
- Решение проблемы InvalidInputException в DuckDB при работе с PyArrow и подсчёте строк
- Введение
- Описание проблемы
- Причины возникновения ошибки
- Решения
- 1. Проверка и очистка данных
- 2. Уточнение запроса
- 3. Использование фильтров
- 4. Обновление библиотек
- 5. Обращение к документации
- 6. Обработка данных с использованием 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
запросы выполняются успешно.
Причины возникновения ошибки
-
Проблемы с типами данных: Ошибка может быть связана с тем, как DuckDB обрабатывает невидимые (null) значения в столбцах. Если в ваших данных имеются строки, не имеющие корректных значений для некоторых колонок, это может вызвать конфликт при попытке выполнить общий подсчёт.
-
Отсутствие явного указания типов данных: DuckDB может не удачно обрабатывать отсутствие информации о структуре данных при выполнении запроса, требующего полной проверки всех строк.
-
Версия библиотек: Вы используете версии
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 или искать помощь в сообществах разработчиков.