Как выполнять запрос к большому файлу с помощью pandas (или альтернативы)?

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

У меня есть большой файл (6 ГБ, около 17 миллионов строк) с 5 столбцами. Я хочу использовать первый столбец в качестве ключа и извлечь остальные 4 столбца. Я хочу задать несколько ключей. Мой код выглядит так:

import pandas as pd

df = pd.read_csv('large_file.gz',
                 chunksize=1000000)

key = "find_this" # элемент из столбца 1

for data in df:
    if key in data['col1'].tolist():
        found = data[data['col1'] == key]
        break

print(found)

Как я могу оптимизировать скорость работы также для нескольких элементов?

ИЗМЕНЕНИЕ:
Я в основном хочу создать сокращённую локальную базу данных dbSNP, где я могу запрашивать геномное местоположение (хромосома, позиция, референтный, альтернативный) с использованием rsID.

Для этого я скачал этот VCF (16 ГБ) и предварительно обработал его с помощью awk

gzcat 00-All.vcf.gz | grep -v ## | awk '{print $3, $1, $2, $4, $4}' | gzip > 00-All_relevant.vcf.gz

Из этого файла я хочу запрашивать #CHROM, POS, REF и ALT с использованием столбца ID.

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

def stream_rows(path, max_len):
    with gzip.open(path, 'rt', encoding='utf-8') as file:
        next(file)  # Пропустить заголовок
        for line in file:
            first_col = line[:max_len]  # Извлечь первый столбец до max_len символов
            yield first_col
def get_minibatch(row_stream, size, key):
    try:
        for _ in range(size):
            row = next(row_stream)
            if row == key:
                return True  # Ключ найден
    except StopIteration:
        pass  # Достигнут конец потока
    
    return False  # Ключ не найден

Теперь вы можете читать строки CSV-файла, не загружая его полностью в ОЗУ. Вы можете использовать эти функции, как показано ниже:

row_stream=stream_rows(path, 20)
found=get_minibatch(row_stream,1000, key)

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

Для работы с большими файлами, превышающими доступную оперативную память, библиотека Pandas может использовать механизм «chunksize». Однако, если вы стремитесь к более эффективному поиску строк по нескольким ключам, есть альтернативные подходы, которые могут повысить производительность. Ниже я предложу решение, которое включает использование Pandas, а также более оптимизированный метод без загрузки всего файла в память.

Использование Pandas с Chunksize

Если вы все же хотите продолжать использовать библиотеку Pandas, модифицируйте ваш код следующим образом, чтобы ускорить процесс поиска для нескольких ключей:

import pandas as pd

# Загрузка файла частями
chunk_size = 1000000
keys = ["key1", "key2", "key3"]  # Список ключей для поиска
found_rows = []  # Список для хранения найденных строк

for chunk in pd.read_csv('large_file.gz', chunksize=chunk_size):
    # Фильтруем строки исходя из наличия ключей в первой колонке
    filtered_chunk = chunk[chunk['col1'].isin(keys)]

    # Добавляем найденные строки в наш список
    found_rows.append(filtered_chunk)

# Объединяем все найденные строки в один DataFrame
result = pd.concat(found_rows, ignore_index=True)
print(result)

Использование Python-генераторов для обработки данных

Для большего контроля и уменьшения нагрузки на память можно использовать Python-генераторы для построчной обработки файла. Это подход более низкого уровня, который позволит вам не загружать всю таблицу целиком в память:

import gzip

def stream_rows(filepath):
    with gzip.open(filepath, 'rt', encoding='utf-8') as f:
        header = f.readline()  # Пропустить заголовок
        for line in f:
            yield line.strip().split('\t')  # Предполагаем, что разделитель - табуляция

def query_keys(filepath, keys):
    keys_set = set(keys)  # Преобразуем список ключей в множество для быстрого поиска
    results = []

    for row in stream_rows(filepath):
        if row[0] in keys_set:  # Проверяем, есть ли ключ в первой колонке
            results.append(row)  # Сохраняем строку, если ключ найден

    return results

# Запустим поиск
found_rows = query_keys('00-All_relevant.vcf.gz', ["rsID1", "rsID2"])
for row in found_rows:
    print(row)

Заключение

Выбор метода зависит от ваших требований к памяти и производительности. Используя Pandas с частичной загрузкой или обращаясь к правилам генерации, вы сможете интегрировать несколько ключей в ваш поиск и обрабатывать большие объемы данных более эффективно. Если файл очень большой, рекомендуется использовать генераторы, которые значительно экономят объем оперативной памяти.

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

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