Pracuję z dużym plikiem csv (> 500 000 kolumn x 4033 wiersze) i moim celem jest uzyskanie sumy wszystkich liczb w wierszu, z wyjątkiem trzech pierwszych komórek pierwszego wiersza, które są tylko opisowe próbki. Chciałbym skorzystać z pakietu pandy.

Zbiór danych wygląda mniej więcej tak:

label   Group     numOtus   Otu0000001  Otu0000002  Otu0000003  Otu0000004  ... Otu0518246  sum
00.03   1.118234  518246    0           62          275         0           ... 5            ?

Próbowałem kilku różnych rzeczy, ale żadna z nich nie działała.

Nie mogę po prostu użyć read_csv z pand, a następnie z nim pracować, ponieważ plik jest zbyt duży (4 GB). Więc spróbowałem pętli for, otwierając po jednym wierszu na raz, ale nie otrzymuję tego, czego się spodziewałem. Ostateczne dane wyjściowe powinny być kolumną z sumą w wierszu. Jakieś pomysły?

lst = []
for line in range(4033):
    l = pd.read_csv("doc.csv", sep = "\t", nrows=1, low_memory=false)
    l = l.drop(columns=['label', 'Group', "numOtus"])
    x = l[list(l.columns)].sum(axis=1, numeric_only=float)
    lst.append(x)
0
Sandra Silva 18 grudzień 2019, 12:24
1
Twój kod odczytuje tylko pierwszy wiersz 4033 razy,
 – 
Shijith
18 grudzień 2019, 12:42

3 odpowiedzi

Możesz użyć dask, który jest specjalnie do tego stworzony.

import dask.dataframe as dd

dd.read_csv("doc.csv", sep = "\t").sum().compute()
1
ignoring_gravity 18 grudzień 2019, 12:27
Dziękuję! Nie wiedziałem o zmierzchu. Jednak otrzymuję ten błąd: ValueError: Próbka nie jest wystarczająco duża, aby zawierać co najmniej jeden wiersz danych. Zwiększ liczbę bajtów w sample w wywołaniu do read_csv/read_table
 – 
Sandra Silva
18 grudzień 2019, 12:35
Czy próbowałeś zwiększyć sample, np. dzwonisz z sample=1e9?
 – 
ignoring_gravity
18 grudzień 2019, 12:36
Przepraszam, moja wina, chodziło mi o sample=10**9
 – 
ignoring_gravity
18 grudzień 2019, 12:46

Innym rozwiązaniem poza dask jest użycie parametru chunksize w pd.read_csv, a następnie pd.concat swoich porcji. Szybki przykład:

chunksize = 1000
l = pd.read_csv('doc.csv', chunksize=chunksize, iterator=True)
df = pd.concat(l, ignore_index=True)

Dodatek: Aby zrobić coś z kawałkami jeden po drugim, możesz użyć:

chunksize = 1000
for chunk in pd.read_csv('doc.csv', chunksize=chunksize, iterator=True):
    # do something with individual chucks there

Aby zobaczyć postęp, możesz rozważyć użycie tqdm.

from tqdm import tqdm

chunksize = 1000
for chunk in tqdm(pd.read_csv('doc.csv', chunksize=chunksize, iterator=True)):
    # do something with individual chucks there
2
Péter Leéh 18 grudzień 2019, 15:43
Myślę, że powinni obliczyć liczbę przed połączeniem, czyż nie? W przeciwnym razie nie widzę, jak unikają problemu z błędami pamięci
 – 
ignoring_gravity
18 grudzień 2019, 12:37
Leéh Próbuję tego podejścia, ale trwa to zbyt długo. Nawet jeśli wykonam %timeit, aby przewidzieć, ile czasu zajmie, kod nie kończy działania. Jakiś pomysł, co mogę zrobić?
 – 
Sandra Silva
18 grudzień 2019, 15:25
%timeit nie służy do przewidywania, które uruchomi funkcję wiele razy. Jak widzę w twoim pytaniu, problem polega na tym, że parametr chucksize określa liczbę wierszy na porcję. Prawdziwym wąskim gardłem jest to, że masz ponad 500 tys. kolumn i tylko 4033 wierszy. Spróbuj zmniejszyć wielkość kawałka do około 500 - 1000 lub nawet mniej.
 – 
Péter Leéh
18 grudzień 2019, 15:31
Ponownie zaktualizowałem odpowiedź. Jaki wynik uzyskasz, dodając tqdm?
 – 
Péter Leéh
18 grudzień 2019, 15:44
Następnie powinieneś po prostu poczekać na ostateczny wynik.
 – 
Péter Leéh
18 grudzień 2019, 17:00

Możesz używać pandas.Series.append i pandas.DataFrame.sum wraz z pandas.DataFrame.iloc, podczas czytania danych w kawałkach,

row_sum = pd.Series([])
for chunk in pd.read_csv('doc.csv',sep = "\t" ,chunksize=50000):
    row_sum = row_sum.append(chunk.iloc[:,3:].sum(axis = 1, skipna = True))
0
Shijith 18 grudzień 2019, 13:12
Kiedy zaczynam uruchamiać kod, nigdy się nie kończy. Nawet %timeit się nie kończy. Jakiś pomysł, co mogę zrobić?
 – 
Sandra Silva
18 grudzień 2019, 15:35
Czy możesz uruchomić kod i=0 for chunk in pd.read_csv('doc.csv',sep = "\t" ,chunksize=50000): print(i) i+=1
 – 
Shijith
18 grudzień 2019, 15:57