2016-03-14 26 views
5

W pandach mogę po prostu użyć pandas.io.parser.read_csv("file.csv", nrows=10000), aby uzyskać pierwsze 10000 linii pliku csv.Uzyskaj ostatnie 10000 linii pliku csv.

Ale ponieważ mój plik csv jest ogromny, a ostatnie wiersze są bardziej istotne niż te pierwsze, chciałbym przeczytać ostatnie 10000 linii. Nie jest to jednak łatwe, nawet jeśli znam długość pliku, ponieważ pomijając pierwsze 990000 wierszy pliku csv o wartości 1000000 przy użyciu pandas.io.parser.read_csv("file.csv", nrows=10000, skiprows=990000), pierwsza linia, która zawiera nagłówek pliku, jest również pomijana. (header=0 jest mierzony po zastosowaniu skiprows, więc to też nie pomaga.)

Jak uzyskać ostatnie 10000 linii z pliku csv z nagłówkiem w linii 0, najlepiej bez znajomości długości pliku w wierszach ?

+0

Czy jesteś w systemie Linux lub OSX? Jeśli tak, to używanie 'tail -n pliku 10000> file2' będzie prawdopodobnie najłatwiejsze ... – Carpetsmoker

+0

Uderzając w pomysł @Carpetsmoker, jeśli nalegasz na używanie' Python', możesz wywołać to na 'subprocess.call () ': P – Mai

+0

@Carpetsmoker, ale potrzebuje również nagłówka. Powinien mieć postać 'head -n 1 file> file2; tail -n plik 10000 >> file2' –

Odpowiedz

5

Można najpierw obliczyć swój rozmiar pliku z:

size = sum(1 for l in open('file.csv')) 

następnie użyć skiprows z range:

df = pd.read_csv('file.csv', skiprows=range(1, size - 10000)) 

EDIT

Jak @ivan_pozdeev wymienionego z tego rozwiązania ty trzeba przejść dwa razy do pliku. Próbowałem odczytać cały plik z pandami, a następnie użyć metody tail, ale ta metoda wolała wtedy sugerować.

Przykład dataframe:

pd.DataFrame(np.random.randn(1000000,3), columns=list('abc')).to_csv('file.csv') 

Timing

def f1(): 
    size = sum(1 for l in open('file.csv')) 
    return pd.read_csv('file.csv', skiprows=range(1, size - 10000)) 

def f2(): 
    return pd.read_csv('file.csv').tail(10000) 

In [10]: %timeit f1() 
1 loop, best of 3: 1.8 s per loop 

In [11]: %timeit f2() 
1 loop, best of 3: 1.94 s per loop 
+0

Uwaga: to przechodzi przez cały plik dwa razy. Nie, żebym (chętnie) widział lepszy sposób ... –

+0

@ivan_pozdeev Myślałem, że z 'pd.read_csv ('file.csv'). Tail (10000)' będzie to szybsze, ale z czasem jest nieco wolniej. –

+2

Z 'tail', przypuszczam, najpierw przeczytałeś _wszystkie dane w' DataFrame', a następnie weź plaster. Nie tylko jest to wolniejsze, ryzyko wyczerpania pamięci. –

1

Jedynym sposobem, aby wziąć dokładnie ciągu ostatnich n wierszy jest as per Anton Protopopov najpierw przejść przez cały plik, licząc linii.

Ale w następnym etapie, biorąc ich optymalizacja może być wykonana (co tail robi):

  • as you go, zapisać przesunięcia linii w buforze kołowym o długości N. Następnie na koniec, najstarszą pozycją w buforze będzie wymagane przesunięcie. W takim przypadku wystarczy obiekt f.seek() w obiekcie pliku zgodnie z Working with 10+GB dataset in Python Pandas.

znacznie szybszy sposób, że nie obejmuje przeżywa całego pliku byłoby nie wymagają dokładnej liczby linii: z tego, co widzę, trzeba tylko dowolna duża ilość. tak, możesz:

  • uzyskać przybliżone oszacowanie przesunięcia trzeba starać się (np obliczyć/oszacować średnią długość linii)
  • szukać tam, potem do następnego (lub previous) Podział wiersza

    To wymaga szczególnej ostrożności, jeśli możesz dysponować danymi z osadzonymi liniami podziału: w takim przypadku nie ma możliwości sprawdzenia, które cytaty są otwierane i które zamykają się. Musisz przyjąć założenia dotyczące tego, co może, a co nie może być w cytatach z wewnątrz i poza nim ...a nawet jak daleko szukać cytatu, aby dowiedzieć się, czy podział linii jest osadzony!

0

Można spróbować tail od pand, zwraca ostatnie n wierszy

df.tail(10000) 
3

Korzystanie @Anton Protopopow przykładowy plik. Odczytywanie częściowego pliku i nagłówka w oddzielnych operacjach jest DUŻO tańsze niż czytanie całego pliku.

Tylko bezpośrednio odczytać końcowe wiersze

In [22]: df = read_csv("file.csv", nrows=10000, skiprows=990001, header=None, index_col=0) 

In [23]: df 
Out[23]: 
       1   2   3 
0         
990000 -0.902507 -0.274718 1.155361 
990001 -0.591442 -0.318853 -0.089092 
990002 -1.461444 -0.070372 0.946964 
990003 0.608169 -0.076891 0.431654 
990004 1.149982 0.661430 0.456155 
...   ...  ...  ... 
999995 0.057719 0.370591 0.081722 
999996 0.157751 -1.204664 1.150288 
999997 -2.174867 -0.578116 0.647010 
999998 -0.668920 1.059817 -2.091019 
999999 -0.263830 -1.195737 -0.571498 

[10000 rows x 3 columns] 

Dość szybko to zrobić

In [24]: %timeit read_csv("file.csv", nrows=10000, skiprows=990001, header=None, index_col=0) 
1 loop, best of 3: 262 ms per loop 

dość tanie, aby określić długość pliku a-priori

In [25]: %timeit sum(1 for l in open('file.csv')) 
10 loops, best of 3: 104 ms per loop 

odczytywane nagłówek

In [26]: df.columns = read_csv('file.csv', header=0, nrows=1, index_col=0).columns 

In [27]: df 
Out[27]: 
       a   b   c 
0         
990000 -0.902507 -0.274718 1.155361 
990001 -0.591442 -0.318853 -0.089092 
990002 -1.461444 -0.070372 0.946964 
990003 0.608169 -0.076891 0.431654 
990004 1.149982 0.661430 0.456155 
...   ...  ...  ... 
999995 0.057719 0.370591 0.081722 
999996 0.157751 -1.204664 1.150288 
999997 -2.174867 -0.578116 0.647010 
999998 -0.668920 1.059817 -2.091019 
999999 -0.263830 -1.195737 -0.571498 

[10000 rows x 3 columns]