Як я можу фільтрувати рядки під навантаженням у функції Pandas read_csv?


95

Як я можу відфільтрувати, які рядки CSV завантажуються в пам’ять за допомогою панд? Це здається варіантом, який слід знайти read_csv. Мені чогось не вистачає?

Приклад: у нас CSV із стовпчиком позначки часу, і ми хотіли б завантажити лише ті рядки, які з позначкою часу перевищують задану константу.

Відповіді:


165

Немає можливості фільтрувати рядки перед завантаженням файлу CSV в об’єкт pandas.

Ви можете завантажити файл, а потім фільтрувати за допомогою df[df['field'] > constant], або якщо у вас дуже великий файл, і вас турбує нестача пам’яті, використовуйте ітератор і застосовуйте фільтр під час об’єднання фрагментів вашого файлу, наприклад:

import pandas as pd
iter_csv = pd.read_csv('file.csv', iterator=True, chunksize=1000)
df = pd.concat([chunk[chunk['field'] > constant] for chunk in iter_csv])

Ви можете змінювати значення відповідно chunksizeдо вашої доступної пам'яті. Детальніше див. Тут .


адже чи chunk['filed']>constantможу я поставити його між 2 постійними значеннями? Наприклад: константа1> шматок ['поле']> константа2. Або я можу використовувати "в діапазоні"?
weefwefwqg3

1
Спробуйте:chunk[(chunk['field'] > constant2)&(chunk['field']<constant1)]
Йоганнес Вакс

У цьому немає .loc? chunk.loc[chunk['field'] > constant]
Вінсент

1
Ви можете використовувати логічні маски з або без .loc. Я не думаю, що .locіснував ще в 2012 році, але я думаю, що в наші дні використання .locє трохи більш явним.
Матті Джон

8

Я не знайшов прямого способу зробити це в контексті read_csv. Однак read_csvповертає DataFrame, який можна відфільтрувати, вибравши рядки за логічним вектором df[bool_vec]:

filtered = df[(df['timestamp'] > targettime)]

Це вибір усіх рядків у df (якщо df - це будь-який DataFrame, наприклад, результат read_csvвиклику, який, принаймні, містить стовпець datetime timestamp), для яких значення в timestampстовпці перевищують значення цільового часу. Подібне запитання .


1
Я не впевнений у цьому, але я відчуваю, що це буде надзвичайно важко для використання пам'яті.
Натан,

2

Якщо відфільтрований діапазон суміжний (як це зазвичай буває з часовими (штампними) фільтрами), то найшвидшим рішенням є жорстке кодування діапазону рядків. Просто комбінуйте skiprows=range(1, start_row)з nrows=end_rowпараметрами. Тоді імпорт займає секунди, де прийняте рішення займе хвилини. Кілька експериментів з початковими даними start_rowне є величезними витратами, враховуючи економію часу імпорту. Зверніть увагу, що ми зберегли рядок заголовка за допомогою range(1,..).


-3

Ви можете вказати nrowsпараметр.

import pandas as pd df = pd.read_csv('file.csv', nrows=100)

Цей код добре працює у версії 0.20.3.


1
OP запитує, як фільтрувати, не обмежуючи кількість прочитаних рядків. Ось чому я підтримав вашу відповідь.
Роман Орак

-4

Якщо ви використовуєте Linux, ви можете використовувати grep.

# to import either on Python2 or Python3
import pandas as pd
from time import time # not needed just for timing
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


def zgrep_data(f, string):
    '''grep multiple items f is filepath, string is what you are filtering for'''

    grep = 'grep' # change to zgrep for gzipped files
    print('{} for {} from {}'.format(grep,string,f))
    start_time = time()
    if string == '':
        out = subprocess.check_output([grep, string, f])
        grep_data = StringIO(out)
        data = pd.read_csv(grep_data, sep=',', header=0)

    else:
        # read only the first row to get the columns. May need to change depending on 
        # how the data is stored
        columns = pd.read_csv(f, sep=',', nrows=1, header=None).values.tolist()[0]    

        out = subprocess.check_output([grep, string, f])
        grep_data = StringIO(out)

        data = pd.read_csv(grep_data, sep=',', names=columns, header=None)

    print('{} finished for {} - {} seconds'.format(grep,f,time()-start_time))
    return data

1
Використання grep - це серйозно поганий вибір з кількох причин. 1) це повільно 2) це не портативно 3) це не панди або python (ви можете використовувати регулярні вирази прямо всередині python), тому я підтримав вашу відповідь
Ахмед Масуд

Ваше рішення працює не на всіх платформах, а також воно включає Grep. Це є причиною голосування проти.
Роман Орак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.