2017-02-14 15 views
3

Если у меня есть файл csv, который слишком велик для загрузки в память с помощью pandas (в данном случае 35gb), я знаю, что можно обрабатывать файл в кусках с помощью chunksize.Загрузить фрейм данных pandas с chunksize, определяемый переменной столбца

Однако я хочу знать, можно ли изменить chunksize на основе значений в столбце.

У меня есть столбец ID, а затем несколько строк для каждого идентификатора с информацией, например:

ID, Time, x, y 
sasd, 10:12, 1, 3 
sasd, 10:14, 1, 4 
sasd, 10:32, 1, 2 
cgfb, 10:02, 1, 6 
cgfb, 10:13, 1, 3 
aenr, 11:54, 2, 5 
tory, 10:27, 1, 3 
tory, 10:48, 3, 5 
ect... 

Я не хочу, чтобы отделить идентификаторы в различные куски. например, будут обработаны куски размером 4:

ID, Time, x, y 
sasd, 10:12, 1, 3 
sasd, 10:14, 1, 4 
sasd, 10:32, 1, 2 
cgfb, 10:02, 1, 6 
cgfb, 10:13, 1, 3 <--this extra line is included in the 4 chunk 

ID, Time, x, y 
aenr, 11:54, 2, 5 
tory, 10:27, 1, 3 
tory, 10:48, 3, 5 
... 

Возможно ли это?

Если не возможно, используя библиотеку CSV с циклом вдоль линий:

for line in file: 
    x += 1 
    if x > 1000000 and curid != line[0]: 
     break 
    curid = line[0] 
    #code to append line to a dataframe 

хотя я знаю, что это было бы создать только один кусок, и для петель занимает много времени, чтобы обработать.

+0

Где хранится файл? Один из способов - предварительно отфильтровать идентификатор (возможно, если вы извлекаете извлечение базы данных, используя 'SELECT * FROM ... WHERE ID == BLAH'), создавая другой файл для каждого уникального значения идентификатора. – blacksite

+0

К сожалению, это невозможно, у меня нет доступа к базе данных. –

+0

Это может быть PITA, но я думаю, что это сработает: что делать, если вы попытались использовать 'chunksize' прямо сейчас, перелистывая весь файл 35gb и создавая индивидуальный CSV для каждого уникального значения ID ('set (df ['ID'])')? Затем для каждой строки вашего более крупного файла вы пишете (читаете: добавьте) эту строку в существующий файл идентификатора, соответствующий идентификатору этой строки? Это было бы не слишком сложно закодировать, хотя я сомневаюсь, как долго это может занять ... Просто мысль! В противном случае, боюсь, я не могу больше помочь. – blacksite

ответ

3

Если вы перебираете файл csv по строкам, вы можете yield кусков с генератором в зависимости от любого столбца.

Рабочий пример:

import pandas as pd 

def iter_chunk_by_id(file): 
    csv_reader = pd.read_csv(file, iterator=True, chunksize=1, header=None) 
    first_chunk = csv_reader.get_chunk() 
    id = first_chunk.iloc[0,0] 
    chunk = pd.DataFrame(first_chunk) 
    for l in csv_reader: 
     if id == l.iloc[0,0]: 
      id = l.iloc[0,0] 
      chunk = chunk.append(l) 
      continue 
     id = l.iloc[0,0] 
     yield chunk 
     chunk = pd.DataFrame(l) 
    yield chunk 

## data.csv ## 
# 1, foo, bla 
# 1, off, aff 
# 2, roo, laa 
# 3, asd, fds 
# 3, qwe, tre 
# 3, tre, yxc 

chunk_iter = iter_chunk_by_id("data.csv") 

for chunk in chunk_iter: 
    print(chunk) 
    print("_____") 

Выход:

0  1  2 
0 1 foo bla 
1 1 off aff 
_____ 
    0  1  2 
2 2 roo laa 
3 2 jkl xds 
_____ 
    0  1  2 
4 3 asd fds 
5 3 qwe tre 
6 3 tre yxc 
_____ 
+0

Итак, это создаст кусок для каждого идентификатора, как бы вместо этого создать более крупные куски размером 1000000, а затем добавить оставшиеся строки одного и того же идентификатора, чтобы строки одного и того же идентификатора не были в отдельных кусках? –

+0

@JoshuaKidd вы поняли функцию 'iter_chunk_by_id()'? Вы можете легко изменить его в соответствии с вашим новым запросом: добавьте условие 'или' в строку 'if id == l.iloc [0,0]', чтобы продолжить добавление строк в кусок, если длина куска меньше 1000000 (кстати, почему вы удалили мой ответ, как принято?) – elcombato