Jak mogę filtrować, które wiersze pliku CSV mają zostać załadowane do pamięci za pomocą pand? Wydaje się, że jest to opcja, którą należy znaleźć read_csv
. Czy coś mi brakuje?
Przykład: mamy plik CSV z kolumną znacznika czasu i chcielibyśmy załadować tylko wiersze, które mają znacznik czasu większy niż dana stała.
chunk['filed']>constant
Mogę kanapka go między 2 wartości stałych? Np .: stała1> chunk ['pole']> stała2. Czy mogę użyć „w zasięgu”?chunk[(chunk['field'] > constant2)&(chunk['field']<constant1)]
.loc
?chunk.loc[chunk['field'] > constant]
.loc
. Wydaje mi się, że nie.loc
istniało w 2012 roku, ale wydaje mi się, że obecnie używanie.loc
jest nieco bardziej jednoznaczne.Nie znalazłem prostego sposobu na zrobienie tego w kontekście
read_csv
. Jednakread_csv
zwraca DataFrame, którą można filtrować, wybierając wiersze według wektora boolowskiegodf[bool_vec]
:filtered = df[(df['timestamp'] > targettime)]
Oznacza to wybranie wszystkich wierszy w df (przy założeniu, że df jest dowolną ramką DataFrame, taką jak wynik
read_csv
wywołania, która przynajmniej zawiera kolumnę z datą i godzinątimestamp
), dla których wartości wtimestamp
kolumnie są większe niż wartość czasu docelowego. Podobne pytanie .źródło
Jeśli filtrowany zakres jest ciągły (jak to zwykle bywa w przypadku filtrów czasu (stempla)), najszybszym rozwiązaniem jest zakodowanie zakresu wierszy na stałe. Po prostu połącz
skiprows=range(1, start_row)
znrows=end_row
parametrami. Następnie import zajmie kilka sekund, podczas gdy zaakceptowane rozwiązanie zajmie minuty. Kilka eksperymentów z początkiemstart_row
nie jest ogromnym kosztem, biorąc pod uwagę oszczędność czasu importu. Zauważ, że zachowaliśmy wiersz nagłówka za pomocąrange(1,..)
.źródło
Alternatywą dla zaakceptowanej odpowiedzi jest zastosowanie read_csv () do StringIO, uzyskanego przez filtrowanie pliku wejściowego.
with open(<file>) as f: text = "\n".join([line for line in f if <condition>]) df = pd.read_csv(StringIO(text))
To rozwiązanie jest często szybsze niż zaakceptowana odpowiedź, gdy warunek filtrowania zachowuje tylko niewielką część linii
źródło
Jeśli używasz Linuksa, możesz użyć 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
źródło
Możesz określić
nrows
parametr.import pandas as pd df = pd.read_csv('file.csv', nrows=100)
Ten kod działa dobrze w wersji 0.20.3.
źródło