Pandas read_csv işlevinde yüklenen satırları nasıl filtreleyebilirim?


105

Pandalar kullanarak CSV'nin hangi satırlarının belleğe yükleneceğini nasıl filtreleyebilirim? Bu, içinde bulunması gereken bir seçenek gibi görünüyor read_csv. Bir şey mi kaçırıyorum?

Örnek: Zaman damgası sütununa sahip bir CSV'miz var ve yalnızca belirli bir sabitten daha büyük bir zaman damgasına sahip satırları yüklemek istiyoruz.

Yanıtlar:


179

CSV dosyası bir pandas nesnesine yüklenmeden önce satırları filtreleme seçeneği yoktur.

Dosyayı yükleyebilir ve ardından filtreleyebilirsiniz df[df['field'] > constant]veya çok büyük bir dosyanız varsa ve belleğinizin bitmesinden endişeleniyorsanız, bir yineleyici kullanın ve dosyanızın parçalarını birleştirirken filtreyi uygulayın, örneğin:

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])

chunksizeKullanılabilir belleğinize uyacak şekilde değiştirebilirsiniz . Daha fazla ayrıntı için buraya bakın.


için chunk['filed']>constantben 2 sabit değerler arasına sandviç olabilir? Örneğin: sabit1> yığın ['alan']> sabit2. Veya 'aralık içinde' kullanabilir miyim?
weefwefwqg3

1
Deneyin:chunk[(chunk['field'] > constant2)&(chunk['field']<constant1)]
Johannes Wachs

Bu bir eksik .locmi? chunk.loc[chunk['field'] > constant]
Vincent

1
Boole maskelerini olsun veya olmasın kullanabilirsiniz .loc. .loc2012'de var olduğunu sanmıyorum , ancak bugünlerde kullanmak .locbiraz daha açık.
Matti John

10

Bağlamında bunu yapmanın kolay bir yolunu bulamadım read_csv. Ancak, read_csvsatırları boole vektörüne göre seçerek filtrelenebilen bir DataFrame döndürür df[bool_vec]:

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

Bu, sütundaki değerlerin targettime değerinden daha büyük olduğu df'deki tüm satırları seçmektir (df'nin, bir read_csvçağrının sonucu gibi , en azından bir tarihsaat sütunu içeren herhangi bir DataFrame olduğu varsayılır timestamp) timestamp. Benzer soru .


1
Bundan emin değilim, ancak bunun bellek kullanımı üzerinde aşırı derecede ağır olacağını hissediyorum.
Nathan

3

Filtrelenen aralık bitişikse (genellikle zaman (damga) filtrelerinde olduğu gibi), o zaman en hızlı çözüm satır aralığını sabit kodlamaktır. Basitçe birleştirmek skiprows=range(1, start_row)ile nrows=end_rowparametreler. Ardından, kabul edilen çözümün dakikalar alacağı içe aktarma işlemi saniyeler sürer. start_rowİthalat sürelerindeki tasarruf göz önüne alındığında, ilk ile birkaç deney, çok büyük bir maliyet değildir. Kullanarak başlık satırını tuttuğumuza dikkat edin range(1,..).


0

Kabul edilen yanıta bir alternatif, girdi dosyasını filtreleyerek elde edilen bir StringIO'ya read_csv () uygulamaktır.

with open(<file>) as f:
    text = "\n".join([line for line in f if <condition>])

df = pd.read_csv(StringIO(text))

Filtreleme koşulu satırların yalnızca küçük bir bölümünü koruduğunda, bu çözüm genellikle kabul edilen yanıttan daha hızlıdır.


-3

Linux kullanıyorsanız, grep kullanabilirsiniz.

# 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 kullanmak, birkaç nedenden dolayı ciddi şekilde kötü bir seçimdir. 1) yavaş 2) taşınabilir değil 3) pandalar ya da python değil (normal ifadeleri doğrudan python içinde kullanabilirsiniz) bu yüzden cevabınızı reddettim
Ahmed Masud

Çözümünüz tüm platformlarda çalışmaz ve ayrıca Grep içerir. Olumsuz oylamanın nedeni budur.
Roman Orac

-3

nrowsParametre belirtebilirsiniz .

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

Bu kod, 0.20.3 sürümünde iyi çalışır.


1
OP, okunan satır sayısını sınırlamayan nasıl filtreleneceğini soruyor. Bu yüzden cevabınızı reddettim.
Roman Orac
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.