2016-09-27 5 views
8

У меня есть большой файл (2 ГБ) категориальных данных (в основном «Нан» - но заполненный здесь и там с фактическими значениями), который слишком велик, чтобы читать в единый кадр данных , У меня было довольно сложное время, когда я собирался создать объект для хранения всех уникальных значений для каждого столбца (что является моей целью - в конечном итоге мне нужно разложить это на моделирование)Pythonic способ вырастить список списков

То, что я закончил, это чтение файла в кусках в dataframe, а затем получить уникальные значения каждого столбца и сохранить их в списке списков. Мое решение работает, но, казалось, было самым непитоновым - есть ли более чистый способ сделать это в Python (вер. 3.5). Я знаю количество столбцов (~ 2100).

import pandas as pd 
#large file of csv separated text data 
data=pd.read_csv("./myratherlargefile.csv",chunksize=100000, dtype=str) 

collist=[] 
master=[] 
i=0 
initialize=0 
for chunk in data: 
    #so the first time through I have to make the "master" list 
    if initialize==0: 
     for col in chunk: 
      #thinking about this, i should have just dropped this col 
      if col=='Id': 
       continue 
      else: 
       #use pd.unique as a build in solution to get unique values 
       collist=chunk[col][chunk[col].notnull()].unique().tolist() 
       master.append(collist) 
       i=i+1 
    #but after first loop just append to the master-list at 
    #each master-list element 
    if initialize==1: 
     for col in chunk: 
      if col=='Id': 
       continue 
      else: 
       collist=chunk[col][chunk[col].notnull()].unique().tolist() 
       for item in collist: 
        master[i]=master[i]+collist 
       i=i+1 
    initialize=1 
    i=0 

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

i=0 
names=chunk.columns.tolist() 
for item in master: 
    master[i]=list(set(item)) 
    master[i]=master[i].append(names[i+1]) 
    i=i+1 

таким образом мастер [я] дает мне имя столбца, а затем список уникальных значений - сырая нефть, но он действительно работает - моя главная проблема заключается в том, чтобы создать список «лучше», если это возможно.

+0

Вы рассмотрели с помощью генератора лениво читать файл? (поиск ключевого слова yield) – salparadise

+0

Это может сделать трюк. Я не очень хорошо разбираюсь в итераторах и генераторах, но беглый взгляд на ключевое слово yield, предложенное, кажется, находится в правильном направлении. – RDS

+0

Это фактически используется генератор под капотом. Чанкиз делает именно это. Из любопытства вы работаете на 32 или 64-битной машине/питоне? 'import sys; print (sys.maxsize) 'должен работать до тех пор, пока вы запускаете python 2.6 –

ответ

8

Я предложил бы вместо list из list с использованием collections.defaultdict(set).

Допустим, вы начинаете с

uniques = collections.defaultdict(set) 

Теперь петля может стать чем-то вроде этого:

for chunk in data: 
    for col in chunk: 
     uniques[col] = uniques[col].union(chunk[col].unique()) 

Обратите внимание, что:

  1. defaultdict всегда имеет set для uniques[col] (это что это за место), поэтому вы можете пропустить initialized и прочее.

  2. Для данного col вы просто обновляете запись объединением текущего набора (который изначально пуст, но это не имеет значения) и новых уникальных элементов.

Редактировать

Как отмечает Раймонд Hettinger (спасибо!), То лучше использовать

 uniques[col].update(chunk[col].unique()) 
+0

Вау - это трюк в 1/3 кода. Мне тоже нужно работать над диктофонами. Отлично сработано. – RDS

+0

@RDS Спасибо. Мне понравился ваш вопрос. Всего наилучшего. –

+0

Это будет выглядеть лучше с '' set.update'', а не '' set.union''. –