2016-03-14 9 views
5

В pandas я могу просто использовать pandas.io.parser.read_csv("file.csv", nrows=10000), чтобы получить первые 10000 строк файла csv.Получить последние 10000 строк файла csv

Но поскольку мой файл csv огромен, а последние строки более актуальны, чем первые, я бы хотел прочитать последние 10000 строк. Тем не менее, это не так просто, даже если я знаю длину файла, потому что если я пропущу первые 990000 строк из 1000000 строк csv-файла, используя pandas.io.parser.read_csv("file.csv", nrows=10000, skiprows=990000), также будет пропущена первая строка, содержащая заголовок файла. (header=0 измеряется после skiprows применяется, так что это не помогает.)

Как получить последние 10000 строк из файла CSV с заголовком в строке 0, предпочтительно, не зная длину файла в строках ?

+0

Вы используете систему Linux или OSX? Если это так, то использование 'tail -n 10000 file> file2', вероятно, будет самым простым ... – Carpetsmoker

+0

Нажав на идею @Carpetsmoker, если вы настаиваете на использовании' Python', вы можете вызвать это на 'subprocess.call () ': P – Mai

+0

@Carpetsmoker, но ему также нужен заголовок. Он должен быть как 'head -n 1 file> file2; tail -n 10000 file >> file2' –

ответ

5

Вы могли бы сначала рассчитать размер файла с:

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

Затем используйте skiprows с range:

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

EDIT

Как @ivan_pozdeev упоминается с этим решением, которое вы нужно идти хотя файл дважды. Я попытался прочитать весь файл с помощью pandas, а затем использовать метод tail, но этот метод более медленный, чем предполагалось.

Пример 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

Примечание: это проходит через весь файл дважды. Не то чтобы я (с готовностью) видел лучший способ ... –

+0

@ivan_pozdeev Я думал, что с 'pd.read_csv ('file.csv'). Tail (10000)' будет быстрее, но с момента времени это немного медленнее. –

+2

С «хвостом», я предполагаю, вы сначала прочитали _все_ данные в «DataFrame», затем возьмите кусочек. Мало того, что это медленнее, вы рискуете исчерпать память. –

1

Единственный способ взять точно последние N строк as per Anton Protopopov, сначала пройти через весь файл, считая строки.

Но для следующего шага, принимая их, оптимизация может быть сделана (что tail делает):

  • , как вы идете, за исключением смещения линий в кольцевом буфере длиной N. Тогда в конце концов, самым старым элементом в буфере будет требуемое смещение. Тогда все, что требуется, это f.seek() на файл-объект согласно Working with 10+GB dataset in Python Pandas.

Намного более быстрый способ, который не включает в себя проходящие через весь файл будет не требует точного количества строк: от того, что я могу видеть, что вам нужно только произвольное большое количество. Таким образом, вы можете:

  • получить грубую оценку смещения вы должны стремиться (например, рассчитать/оценить среднюю длину линии)
  • искать там, то к следующему (или previous) Разрыв строки

    Это требует особой осторожности, если вы можете иметь данные со встроенными разрывами строк: в этом случае нет надежного способа обнаружить, какие кавычки открываются и которые закрываются. Вы должны делать предположения о том, что может и что не может быть внутри/вне кавычек ...и даже как далеко искать цитату, чтобы узнать, включен ли разрыв строки!

0

Вы можете попробовать tail из панд, он возвращает последние п строк

df.tail(10000) 
3

Использование файла образца @Anton Протопопов. Чтение частичного бита файла и заголовка в отдельных операциях намного дешевле, чем чтение всего файла.

Просто непосредственно прочитать последние строки

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] 

Довольно быстро это сделать

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 

Довольно дешево, чтобы определить длину файла априорного

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

Читать в заголовок

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]