2017-01-03 1 views
0

Так файл CSV Я работаю с внешностью, как:Сортировка/конденсацией большого файла CSV по нескольким столбцам

Date Time,   SegmentID, indicatorvalue 
2016-12-01T00:00:00Z 147649  1 
2016-12-01T00:01:00Z 147649  0 
2016-12-01T00:02:00Z 147649  1 
...     ...   ... 
2016-12-01T00:23:00Z 2938733  0 

ЭСТ.

То, что я хочу, состоит в том, чтобы сконденсировать его в список всех сегментов, а затем процент от того, сколько из записей для этого сегмента имеет значение показателя, связанное по времени суток (AM/IP/PM/OP)

например:

segmentID, Time Period, Percentage 
147649  AM   78 
147649  IP   100 
147649  PM   60 
147649  OP   30 
243546  AM   79 
243546  IP   98 
...   ...   ... 

Моя попытка была создана для цикла, так что для каждого сегмента он будет держать текущую сумму процентных показателей для 4 раза день, то, как только это было что он изменился на новый идентификатор сегмента, он добавит эти значения в строку.

Проблема в том, что идентификаторы сегментов неупорядочены, что приводит к нескольким записям для одного и того же идентификатора сегмента. Я попытался упорядочить файл SegmentID, но файл слишком массивный. Любые предложения по альтернативному подходу?

EDIT: Тот, кто удалил свой комментарий отвечал, что я должен использовать панда, поэтому после того, как несколько исследований, мой код в настоящее время:

import numpy as np 
import pandas as pd 

df=pd.read_csv("data.csv",sep=",",index_col="Segment ID",usecols=["Segment ID","Date Time","indicatorvalue"]) 
df['Date Time'] = ['AM' if '06' <= x[11:13] < '10' 
    else 'IP' if '10' <= x[11:13] < '16' 
    else 'PM' if '16' <= x[11:13] < '19' 
    else 'OP' if '19' <= x[11:13] or x[11:13] < '06' 
    else 'Error' for x in df['Date Time']] 

Теперь мне просто нужно работать, как конденсировать строки с повторяющиеся записи для «Date Time» и «SegmentID» при усреднении их «показателей».

+0

Насколько массивный массив? –

+0

Около 3,5 ГБ, не уверен, сколько строк, но в миллионах –

+0

И сколько памяти доступно и сколько сегментов ожидается? –

ответ

0

мне удалось выработать решение с панды. Код, который я использовал, был:

import pandas as pd 

df=pd.read_csv("data.csv",sep=",",usecols=["Segment ID","Date Time","indicator value"]) 

df['Date Time'] = ['AM' if '06' <= x[11:13] < '10' 
    else 'IP' if '10' <= x[11:13] < '16' 
    else 'PM' if '16' <= x[11:13] < '19' 
    else 'OP' if '19' <= x[11:13] or x[11:13] < '06' 
    else 'Error' for x in df['Date Time']] 

grouped = df.groupby(['Segment ID','Date Time']).mean() 

grouped.to_csv('output.csv', sep =',') 

Я не могу рекомендовать Pandas достаточно.

0

Я предполагаю, что структура входного файла является одной строкой в ​​минуту, дающей начальное время, идентификатор сегмента и значение индикатора.

Если номер сегмента совместим с доступной памятью, я бы просто прочитал входной файл в строке за раз и добавил минуты до 8 счетчиков на сегмент, то есть за время суток и значение индикатора. Это означает, что начальный файл читается только один раз, а не сортируется, и единственное критическое количество - это количество сегментов - если он становится слишком высоким, я бы использовал вместо sqlite3 или dbm базу данных вместо dict.

С текущего примера (с является не CSV), код может быть:

class Segment: 
    labels = ['AM', 'IP', 'PM', 'OP'] 
    def __init__(self, segid): 
     self.id = segid 
     self.values = [ [ 0, 0 ] for i in range(4) ] 
    def add(self, hour, indic): 
     ix = 3 
     if hour >= 6 and hour < 10: ix=0 
     elif hour >= 10 and hour < 16: ix=1 
     elif hour >= 16 and hour < 19: ix = 2 
     self.values[ix][indic] += 1 
    def percent(self, ix): 
     try: 
      return int(.5 + (100 * self.values[ix][1]/
       (self.values[ix][0] + self.values[ix][1]))) 
     except ZeroDivisionError: 
      return 0 

dummy = next(fd) 
splitter = re.compile(' +') 
segments = dict() 
for line in fd: # read and store 
    d, seg, indic = splitter.split(line.strip()) # could be replaced with a csv reader 
    hour = int(d[11:13]) 
    if not seg in segments: 
     segments[seg] = Segment(seg) 
    segments[seg].add(hour, int(indic)) 
for seg in sorted(segments.keys()): # output the stats 
    for ix in range(4): 
     print(seg, Segment.labels[ix], segments[seg].percent(ix)) 

Приведенный выше код не хватает тестов для ошибки или исключительные условия

Смежные вопросы