2014-02-10 2 views
0

Python Gurus,Синтаксический и CSV файлов Реорганизация с Python

В прошлом, я использую Perl, чтобы пройти через очень большие текстовые файлы для интеллектуального анализа данных. Недавно я решил переключиться с тех пор, как считаю, что Python упрощает мне мой код и выясняет, что происходит. Неудачная (или, может быть, удачная?) Вещь о Python заключается в том, что чрезвычайно сложно хранить и упорядочивать данные по сравнению с Perl, так как я не могу создавать хэши хэшей через автовивитацию. Я также не могу суммировать элементы словаря словарей.

Возможно, есть изящное решение моей проблемы.

У меня есть сотни файлов с несколькими сотнями строк данных (все они могут вписываться в память). Цель состоит в том, чтобы объединить эти два файла, но с определенными критериями:

  1. Для каждого уровня (отображается только один уровень ниже) Мне нужно, чтобы создать строку для каждого класса дефектов, который был найден во всех файлах. Не все файлы имеют одинаковые дефекты.

  2. Для каждого уровня и класса дефектов суммируйте все значения GEC & BEC во всех файлах.

  3. Конечный результат должен выглядеть (обновленный выход образца, опечатка):

Уровень defectClass BECtotals GECtotals
1415PA, 0, 643, 1991
1415PA, 1, 1994, 6470
... и так далее .....

Файл один:

Level, defectClass, BEC, GEC 
1415PA,  0,   262, 663 
1415PA,  1,   1138, 4104 
1415PA, 107,  2, 0 
1415PA,  14,   3, 4 
1415PA,  15,   1, 0 
1415PA,  2,   446, 382 
1415PA,  21,   5, 0 
1415PA,  23,   10, 5 
1415PA,  4,   3, 16 
1415PA,  6,  52, 105 

Файл два:

level, defectClass, BEC, GEC 
1415PA, 0,  381, 1328 
1415PA, 1,  856, 2366 
1415PA, 107,  7, 11 
1415PA, 14, 4, 1 
1415PA, 2,  315, 202 
1415PA, 23, 4, 7 
1415PA, 4,  0, 2 
1415PA, 6,  46, 42 
1415PA, 7,  1, 7 

У меня самая большая проблема в том состоянии сделать сложений на словарях. Это код, который я до сих пор (не работает):

import os 
import sys 


class AutoVivification(dict): 
    """Implementation of perl's autovivification feature. Has features from both dicts and lists, 
    dynamically generates new subitems as needed, and allows for working (somewhat) as a basic type. 
    """ 
    def __getitem__(self, item): 
    if isinstance(item, slice): 
     d = AutoVivification() 
     items = sorted(self.iteritems(), reverse=True) 
     k,v = items.pop(0) 
     while 1: 
     if (item.start < k < item.stop): 
      d[k] = v 
     elif k > item.stop: 
      break 
     if item.step: 
      for x in range(item.step): 
      k,v = items.pop(0) 
     else: 
      k,v = items.pop(0) 
     return d 
    try: 
     return dict.__getitem__(self, item) 
    except KeyError: 
     value = self[item] = type(self)() 
     return value 

    def __add__(self, other): 
    """If attempting addition, use our length as the 'value'.""" 
    return len(self) + other 

    def __radd__(self, other): 
    """If the other type does not support addition with us, this addition method will be tried.""" 
    return len(self) + other 

    def append(self, item): 
    """Add the item to the dict, giving it a higher integer key than any currently in use.""" 
    largestKey = sorted(self.keys())[-1] 
    if isinstance(largestKey, str): 
     self.__setitem__(0, item) 
    elif isinstance(largestKey, int): 
     self.__setitem__(largestKey+1, item) 

    def count(self, item): 
    """Count the number of keys with the specified item.""" 
    return sum([1 for x in self.items() if x == item]) 

    def __eq__(self, other): 
    """od.__eq__(y) <==> od==y. Comparison to another AV is order-sensitive 
    while comparison to a regular mapping is order-insensitive. """ 
    if isinstance(other, AutoVivification): 
     return len(self)==len(other) and self.items() == other.items() 
    return dict.__eq__(self, other) 

    def __ne__(self, other): 
    """od.__ne__(y) <==> od!=y""" 
    return not self == other 

for filename in os.listdir('/Users/aleksarias/Desktop/DefectMatchingDatabase/'): 
    if filename[0] == '.' or filename == 'YieldToDefectDatabaseJan2014Continued.csv': 
    continue 
    path = '/Users/aleksarias/Desktop/DefectMatchingDatabase/' + filename 

    for filename2 in os.listdir(path): 
    if filename2[0] == '.': 
     continue 
    path2 = path + "/" + filename2 
    techData = AutoVivification() 

    for file in os.listdir(path2): 
     if file[0:13] == 'SummaryRearr_': 
     dataFile = path2 + '/' + file 
     print('Location of file to read: ', dataFile, '\n') 
     fh = open(dataFile, 'r') 

     for lines in fh: 
      if lines[0:5] == 'level': 
      continue 
      lines = lines.strip() 
      elements = lines.split(',') 

      if techData[elements[0]][elements[1]]['BEC']: 
      techData[elements[0]][elements[1]]['BEC'].append(elements[2]) 
      else: 
      techData[elements[0]][elements[1]]['BEC'] = elements[2] 

      if techData[elements[0]][elements[1]]['GEC']: 
      techData[elements[0]][elements[1]]['GEC'].append(elements[3]) 
      else: 
      techData[elements[0]][elements[1]]['GEC'] = elements[3] 


      print(elements[0], elements[1], techData[elements[0]][elements[1]]['BEC'], techData[elements[0]][elements[1]]['GEC']) 

    techSumPath = path + '/Summary_' + filename + '.csv' 
    fh2 = open(techSumPath, 'w') 
    for key1 in sorted(techData): 
    for key2 in sorted(techData[key1]): 
     BECtotal = sum(map(int, techData[key1][key2]['BEC'])) 
     GECtotal = sum(map(int, techData[key1][key2]['GEC'])) 
     fh2.write('%s,%s,%s,%s\n' % (key1, key2, BECtotal, GECtotal)) 
    print('Created file at:', techSumPath) 
    input('Go check the file!!!!') 

Спасибо, что посмотрели на это !!!!!
Alex

ответ

3

Я собираюсь предложить другой подход: если вы обрабатываете табличные данные, вы должны посмотреть библиотеку pandas. Ваш код становится чем-то вроде

import pandas as pd 

filenames = "fileone.txt", "filetwo.txt" # or whatever 

dfs = [] 
for filename in filenames: 
    df = pd.read_csv(filename, skipinitialspace=True) 
    df = df.rename(columns={"level": "Level"}) 
    dfs.append(df) 

df_comb = pd.concat(dfs) 
df_totals = df_comb.groupby(["Level", "defectClass"], as_index=False).sum() 
df_totals.to_csv("combined.csv", index=False) 

который производит

[email protected]:~/coding/pand$ cat combined.csv 
Level,defectClass,BEC,GEC 
1415PA,0,643,1991 
1415PA,1,1994,6470 
1415PA,2,761,584 
1415PA,4,3,18 
1415PA,6,98,147 
1415PA,7,1,7 
1415PA,14,7,5 
1415PA,15,1,0 
1415PA,21,5,0 
1415PA,23,14,12 
1415PA,107,9,11 

Здесь я читал каждый файл в память одновременно и объединил их в один большой DataFrame (как лист Excel), но мы может так же легко сделать файл операции groupby по файлу, поэтому нам нужно будет иметь только один файл в памяти, если нам понравится.

+0

Это отличное решение! Удивительно, как много вы можете добиться с помощью такого короткого кода. Мне нужно начать изучать все эти библиотеки. –

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