Próbuję zrobić coś dość prostego, wczytując duży plik csv do ramki danych pandy.
data = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2)
Kod albo kończy się niepowodzeniem MemoryError
, albo po prostu nigdy się nie kończy.
Użycie pamięci w menedżerze zadań zatrzymało się na 506 Mb i po 5 minutach braku zmian i braku aktywności procesora w procesie zatrzymałem je.
Używam pand w wersji 0.11.0.
Wiem, że kiedyś występował problem z pamięcią w parserze plików, ale według http://wesmckinney.com/blog/?p=543 powinno to zostać naprawione.
Plik, który próbuję odczytać ma 366 Mb, powyższy kod działa, jeśli skrócę plik do czegoś krótkiego (25 Mb).
Zdarzyło się również, że wyskoczyło mi wyskakujące okienko z informacją, że nie może napisać na adres 0x1e0baf93 ...
Ślad stosu:
Traceback (most recent call last):
File "F:\QA ALM\Python\new WIM data\new WIM data\new_WIM_data.py", line 25, in
<module>
wimdata = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2
)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 401, in parser_f
return _read(filepath_or_buffer, kwds)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 216, in _read
return parser.read()
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 643, in read
df = DataFrame(col_dict, columns=columns, index=index)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 394, in __init__
mgr = self._init_dict(data, index, columns, dtype=dtype)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 525, in _init_dict
dtype=dtype)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 5338, in _arrays_to_mgr
return create_block_manager_from_arrays(arrays, arr_names, axes)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1820, in create_block_manager_from_arrays
blocks = form_blocks(arrays, names, axes)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1872, in form_blocks
float_blocks = _multi_blockify(float_items, items)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1930, in _multi_blockify
block_items, values = _stack_arrays(list(tup_block), ref_items, dtype)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1962, in _stack_arrays
stacked = np.empty(shape, dtype=dtype)
MemoryError
Press any key to continue . . .
Trochę tła - próbuję przekonać ludzi, że Python może zrobić to samo co R. W tym celu próbuję powielić skrypt R, który to robi
data <- read.table(paste(INPUTDIR,config[i,]$TOEXTRACT,sep=""), HASHEADER, DELIMITER,skip=2,fill=TRUE)
R nie tylko udaje się dobrze odczytać powyższy plik, ale nawet czyta kilka z tych plików w pętli for (a następnie robi coś z danymi). Jeśli Python ma problem z plikami o takim rozmiarze, być może toczę przegraną bitwę ...
nrows=something small
do,read_csv
aby upewnić się, że nie jest to rozmiar pliku powodującego problemy, co, jak powiedział Andy, nie powinno mieć miejsca.csv_chunks = pandas.read_csv(filepath, sep = DELIMITER,skiprows = 1, chunksize = 10000)
, a następnie połącz fragmentydf = pandas.concat(chunk for chunk in csv_chunks)
. Nadal interesuje mnie, dlaczego czytanie go za jednym razem nie działa, dla mnie wygląda to na problem z czytnikiem csv.chunksize=1000
hacka do odczytywania csv, a następnie próbuję połączyć wszystkie fragmenty w dużą ramkę danych, w tym momencie pamięć wysadza się, z około 3-4 razy większą ilością pamięci w porównaniu do rozmiaru oryginalnego pliku. Czy ktoś ma pojęcie, dlaczego ramka danych może wybuchnąć?Odpowiedzi:
Ograniczenie pamięci systemu Windows
Błędy pamięci zdarzają się często w Pythonie podczas korzystania z wersji 32-bitowej w systemie Windows. Dzieje się tak, ponieważ procesy 32-bitowe domyślnie otrzymują tylko 2 GB pamięci do gry .
Sztuczki zmniejszające zużycie pamięci
Jeśli nie używasz 32-bitowego Pythona w systemie Windows, ale chcesz poprawić wydajność pamięci podczas czytania plików csv, jest pewna sztuczka.
Funkcja pandas.read_csv przyjmuje opcję o nazwie
dtype
. Dzięki temu pandy wiedzą, jakie typy istnieją w danych CSV.Jak to działa
Domyślnie pandy będą próbowały odgadnąć, jakie dtypy ma twój plik csv. Jest to bardzo ciężka operacja, ponieważ podczas określania typu dtype musi przechowywać wszystkie surowe dane jako obiekty (ciągi znaków) w pamięci.
Przykład
Załóżmy, że Twój plik CSV wygląda tak:
name, age, birthday Alice, 30, 1985-01-01 Bob, 35, 1980-01-01 Charlie, 25, 1990-01-01
Ten przykład nie jest oczywiście problemem wczytywania do pamięci, ale to tylko przykład.
Gdyby pandy miały odczytać powyższy plik csv bez żadnej opcji dtype, wiek byłby przechowywany jako ciągi w pamięci, dopóki pandy nie przeczytają wystarczającej liczby wierszy pliku csv, aby dokonać kwalifikowanego przypuszczenia.
Myślę, że domyślnie w pandach odczytuje się 1 000 000 wierszy przed odgadnięciem typu dtype.
Rozwiązanie
Podając
dtype={'age':int}
jako opcję do.read_csv()
woli, pandy będą wiedzieć, że wiek powinien być interpretowany jako liczba. Oszczędza to dużo pamięci.Problem z uszkodzonymi danymi
Jeśli jednak plik csv byłby uszkodzony, na przykład:
name, age, birthday Alice, 30, 1985-01-01 Bob, 35, 1980-01-01 Charlie, 25, 1990-01-01 Dennis, 40+, None-Ur-Bz
Określenie
dtype={'age':int}
spowoduje przerwanie.read_csv()
polecenia, ponieważ nie może ono rzutować"40+"
na int. Dlatego dokładnie oczyść swoje dane!Tutaj możesz zobaczyć, jak użycie pamięci przez ramkę danych pandy jest znacznie wyższe, gdy elementy zmiennoprzecinkowe są przechowywane jako ciągi:
Spróbuj sam
df = pd.DataFrame(pd.np.random.choice(['1.0', '0.6666667', '150000.1'],(100000, 10))) resource.getrusage(resource.RUSAGE_SELF).ru_maxrss # 224544 (~224 MB) df = pd.DataFrame(pd.np.random.choice([1.0, 0.6666667, 150000.1],(100000, 10))) resource.getrusage(resource.RUSAGE_SELF).ru_maxrss # 79560 (~79 MB)
źródło
read_csv
funkcja robi coś niesamowicie funky, byłbym bardzo zaskoczony, gdyby zużycie pamięci było zauważalnie wyższe.Miałem ten sam problem z pamięcią po prostym odczytaniu pliku tekstowego rozdzielanego tabulatorami o rozmiarze około 1 GB (ponad 5,5 miliona rekordów) i to rozwiązało problem z pamięcią :
df = pd.read_csv(myfile,sep='\t') # didn't work, memory error df = pd.read_csv(myfile,sep='\t',low_memory=False) # worked fine and in less than 30 seconds
Spyder 3.2.3 Python 2.7.13 64 bity
źródło
low_memory=False
powinno zużywać mniej pamięci…Używam Pand na moim Linuksie i napotkałem wiele wycieków pamięci, które zostały rozwiązane dopiero po uaktualnieniu Pandy do najnowszej wersji po sklonowaniu go z github.
źródło
Napotkałem ten problem również, gdy pracowałem na maszynie wirtualnej lub w innym miejscu, w którym pamięć jest ściśle ograniczona. Nie ma to nic wspólnego z pandami, numpy czy csv, ale zawsze się wydarzy, jeśli spróbujesz użyć większej ilości pamięci, której możesz używać, nawet nie tylko w Pythonie.
Jedyną szansą, jaką masz, jest to, czego już próbowałeś, spróbuj rozłożyć to duże na mniejsze kawałki, które pasują do pamięci.
Jeśli kiedykolwiek zadałeś sobie pytanie, o co chodzi w MapReduce, dowiedziałeś się sam ... MapReduce spróbowałoby rozprowadzić porcje na wielu maszynach, spróbowałbyś przetworzyć porcje na jednym komputerze jeden po drugim.
To, czego dowiedziałeś się z konkatenacją plików porcji, może rzeczywiście stanowić problem, być może potrzebna jest kopia w tej operacji ... ale ostatecznie może to uratować Cię w obecnej sytuacji, ale jeśli twój plik csv stanie się trochę większy możesz znowu biec pod tą ścianę ...
Możliwe też, że pandy są tak inteligentne, że w rzeczywistości ładują poszczególne fragmenty danych do pamięci tylko wtedy, gdy coś z nimi zrobisz, na przykład konkatenację z dużym df?
Możesz spróbować kilku rzeczy:
źródło
Nie ma błędu dla Pandas 0.12.0 i NumPy 1.8.0.
Udało mi się stworzyć dużą ramkę DataFrame i zapisać ją w pliku csv, a następnie pomyślnie ją przeczytać. Zobacz przykład tutaj . Rozmiar pliku to 554 Mb (działał nawet dla pliku 1,1 Gb, trwało to dłużej, aby wygenerować plik 1,1 Gb z częstotliwością wykorzystania 30 sekund). Chociaż mam dostępne 4 GB pamięci RAM.
Moja sugestia to spróbuj zaktualizować Pandy. Inną rzeczą, która może się przydać, jest próba uruchomienia skryptu z wiersza poleceń, ponieważ dla R nie używasz Visual Studio (zostało to już zasugerowane w komentarzach do twojego pytania), stąd ma więcej dostępnych zasobów.
źródło
Próbowałem
chunksize
czytając duży plik CSVreader = pd.read_csv(filePath,chunksize=1000000,low_memory=False,header=0)
Odczyt jest teraz listą. Możemy iterować
reader
i zapisywać / dołączać do nowego csv lub możemy wykonać dowolną operacjęfor chunk in reader: print(newChunk.columns) print("Chunk -> File process") with open(destination, 'a') as f: newChunk.to_csv(f, header=False,sep='\t',index=False) print("Chunk appended to the file")
źródło
Dodaj następujące: ratingi = pd.read_csv (..., low_memory = False, memory_map = True )
Moja pamięć z tymi dwoma: # 319.082.496 Bez tych dwóch: # 349.110.272
źródło
Chociaż jest to obejście, a nie tylko poprawka, spróbuję przekonwertować ten plik CSV na JSON (powinno być trywialne) i
read_json
zamiast tego użyć metody - piszę i czytam duże ramki JSON / dataframe (100s MB) w Pandas to sposób bez problemu.źródło