Поиск по блогу

понедельник, 6 апреля 2015 г.

Проект соглашения с самим собой об обработки файлов таблиц AEBto3tables

Пример того, как я пришел к простым правилам обработки спарсенных таблиц. Техника определяет тактику (мое теннисное убеждение), и правила также нельяз написать без учета инструментов, которые используются для обработки.
Я недавно "запал" на Pandas. И только вчера подобрал и попробовал методы для чистки таблиц. Т.е., я еще не освоил "технику" настолько, чтобы не думать о ней, но сосредоточиться на последовательности процессаов и "тактике" перебора файлов...
Наверное, поэтому мне так трудно. Очевидно, что я совершаю методическую ошибку. Я пытаюсь одновременно "ехать на автомобиле и ремонтировать его" (еще одна метафора... только для того, чтобы оправдать собственную глупость.
Здесь я попытался было проверить все чистящие операторы в одном методе в цикле, но влетел в непонятные ошибки, подключил дебаггер... оказалось, что один из файлов (апрель) в папке с заголовком, а остальные - нет... Начал пробовать все подряд, а потом написал-таки правила...

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

Правила папок

  1. Однородные файлы должны быть однотипными (чтобы их можно было обрабатывать в цикле)
  2. Следствие 1 из 1: Все эксперименты и настройки в отдельных временных папках для временных файлаов.
  3. Следствие 2 из 1: Результаты обработки в новую папку с большим номером версии.
  4. Следствие 3 из 1: Во всех файлах папки обязательна метка в имени файла (для фильтра).
  5. Следствие 4 из 1: В некоторых папках можно размещать файлы-комментарии с одинаковыми именами. Например info.txt
  6. Следствие 1 из 5: info.txt нужно создавать автоматически, с якорями (тегами?) для парсинга файлйа, например "date:" (альтернатива - .json)?

Правила просмотра

  1. Шаблон визуального контроля - это .ipynb шаблон в ячейках которого код для циклов по файлам папки.
  2. Визуальный контроль. Считываем по очереди в объект Pandas и печатаем каждый объект - возможен отдельный файл .ipynb. Можно просто в цикле распечатать фрагменты из разнфх мест для каждого файла.
  3. Планирование дальнейших действий. Потом спланировать действия (и их последовтельность) для алгоритма обработки (открытия, перебора, очистки, склеивания)... например, в данном случае выгодно сначала склеить, а потом чистить. Для этого должны быть ячейки - шаблоны со списками возможных действий... Может быть, сразу фрагменты кода использовать? В каждой ячейке свой метод (он уже проверен, потому в перспективе можно их в цикл заряжать... Единственное неудобство - отступы (попробовать TAB Shift+TAB) в Notebook
  4. Логирование (запись плана и произведенных действий) Подчеркиваю, что надо отразить последовательности действий (вызова методов), записи об исправлениях в файлах (можно %load, %write)..., например, если убрать строку-заголовок в первом файле все записи можно обрабатыват в цикле. Запись об этом событии должна быть в тдельной ячейке..., а все дальнейшие плановые события должны быть скопированы и перенесены в файл .ipynb в котором будет записан процесс дальнейшей обработки.
  5. Удаление лишних файлов. Пока не знаю, как это лучше делать... но мусор собирать надо..., поэтому пока надо бы готовить полные пути "старых файлов" для сборщиков мусора. Или просто переимановывать папки, например, добавлять в конец "_bak"
In [ ]:
####Правила работы со столбцами
  1. Проверяем все первоисточники на предмет соответствия едминому шаблону например, COLNAMES =['Brandt', '2014y', '2013y', '1413y', '2014m', '2013m', '1413m', 'Datem']
  2. Для всех объектов DataFrame одна строка заголовков вставляется при считывании csv
  3. Для всех объектов DataFrame определяются NaN для считывании csv

Правила сохранения результатов

Этот фрагмент я пишу после того, как закончил селдующий пост. Там я сцепил вместе и почистил 9 файлов (а нужно 12), получил очередной промежуточный результат. Его, естественно, надо сохранить.

  1. Каждый этап преобразований в отдельную папку (чтобы потом можно было удалить всю папку)
  2. При этом "старые" файлы во вложенных папках (старые - это первоисточники и обработка).
  3. Оставлять ли первоисточники?
  4. Обработку удалять после того, как оттестирован сводный файл?
####Правила редактирования таблиц-исходников
  1. Таблицы-исходники это, то (csv), что вышло из парсера. В этом примере я просто удалил строку заголовка в файле апреля, она создавала большие проблемы, например при вставке столбца строк (object) вида '21-12-2014' оказалось, что в первой строке строка '1413m%', а я потом собирался все это конвертировать в Date64.
  2. Такие ошибки выявляются при визуальном контроле структуры. Как, оставаясь в Notebook, редактировать строки?
  3. !ls '', !tree
  4. !mkdip '' - создать папку для новой версии
  5. %load ''
  6. %%writefile tofilepath """ """

Далее эксперименты, в процессе которых все эти умные мысли посетили мою голову

In [1]:
import sys
In [2]:
sys.path
Out[2]:
['',
 '/usr/lib/python2.7/dist-packages/pybloomfiltermmap-0.3.11-py2.7-linux-i686.egg',
 '/usr/lib/python2.7',
 '/usr/lib/python2.7/plat-linux2',
 '/usr/lib/python2.7/lib-tk',
 '/usr/lib/python2.7/lib-old',
 '/usr/lib/python2.7/lib-dynload',
 '/usr/local/lib/python2.7/dist-packages',
 '/usr/lib/python2.7/dist-packages',
 '/usr/lib/python2.7/dist-packages/PIL',
 '/usr/lib/python2.7/dist-packages/gtk-2.0',
 '/usr/lib/pymodules/python2.7',
 '/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode',
 '/usr/local/lib/python2.7/dist-packages/IPython/extensions']
In [1]:
import pdb
In [2]:
dir(pdb)
Out[2]:
['Pdb',
 'Repr',
 'Restart',
 'TESTCMD',
 '__all__',
 '__builtins__',
 '__doc__',
 '__file__',
 '__name__',
 '__package__',
 '_repr',
 '_saferepr',
 'bdb',
 'cmd',
 'find_function',
 'help',
 'line_prefix',
 'linecache',
 'main',
 'os',
 'pm',
 'post_mortem',
 'pprint',
 're',
 'run',
 'runcall',
 'runctx',
 'runeval',
 'set_trace',
 'sys',
 'test',
 'traceback']
In [3]:
import os
import pandas as pd
#import matplotlib.pyplot as plt
#import numpy as np
In [4]:
# Path to dir with files
DIRPATH = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/1aug2/'

# Insert my columns names in Dataframe objects
COLNAMES =['Brandt', '2014y', '2013y', '1413y', '2014m', '2013m', '1413m', 'Datem']
In [3]:
months = ['january', 'febrary', 'march', 'april', 'may', 'jun',
        'july', 'august','september', 'october','november', 'december']
    
dict = {'january':'31-1', 'febrary':'28-2', 'march':'31-1',
        'april':'30-4', 'may':'31-5', 'jun':'30-6',
        'july':'31-7', 'august':'31-8','september':'30-9', 
        'october':'31-10','november':'30-11', 'december':'31-12'}
In [7]:
pdall =  pd.DataFrame()     

Вот этот код начал выдавать ошибки, в следующем посте я все исправил, результат работы - там, а здесь лишь классический пример ошибочного ламерского подхода. 1) Надо представлять структуру данных 2) Надо иметь четкий план - в данном случае очень важна последовательность чистки...

Например, есть в элементы "-" (во всех столбцах) и "-45.3%" (в дух столбцах), я забабахал str.replace('%','').astype(float) и получил ошибку на элементах "-", о существовании которых "не знал", потому что не удосужился просмотреть исходные файлы ... Надо бы упростить эту процедуру... Вот, пока нашел вариант с PDB

In [ ]:
import pdb; pdb.set_trace()
for csvfile in os.listdir(DIRPATH):
    if csvfile.startswith('eng_car-sales-in'):
        csvfile_path = os.path.join(DIRPATH, csvfile)
        
        pdtemp = pd.read_csv(csvfile_path, error_bad_lines=False, names=COLNAMES)
        
        # Replace '*', '%' and convert object to Int
        pdtemp['Brandt'] = pdtemp['Brandt'].str.replace('*','')
        pdtemp['1413y'] = pdtemp['1413y'].str.replace('%','').astype(float)
        pdtemp['1413m'] = pdtemp['1413m'].str.replace('%','').astype(float)
        
        # Parse month name from filename
        namem = csvfile.split('-')[3]            # 'april' for example
        
        # Replace strings with dict     'april':'30-4', 
        pdtemp['Datem'] = dict[namen] + '-2014'  # '30-4-2014'
        
        #Concat month dataframes to pdall
        pdall = pd.concat(pdall, pdtemp, ignore_index=True)

Вот пример пошагового распечатывания файлов с помошью дебаггера ...надо просто задать точку останова

Если файлы длинные, то надо бы их рассмтривать по-одному..., но как это делать? Пока не догадался. Не будем решать задачи, которых пока нет (длинных файлов)... Здесь лучше отметим, что в выходной поток дебаггера можно ведь и строки (с комментариями записывать... А чтобы сократить количество строк можно на печатьвыводить фрагменты...

In [ ]:
import pdb; pdb.set_trace()
for csvfile in os.listdir(DIRPATH):
    if csvfile.startswith('eng_car-sales-in'):
        csvfile_path = os.path.join(DIRPATH, csvfile)
        
        pdtemp = pd.read_csv(csvfile_path, error_bad_lines=False, names=COLNAMES)
        print (csvfile, pdtemp)

Но сбой произошел... и весь дебаггера исчез... Это можно использовать... Например, на задавать печать в коде, а печатать в объект в дебаггере... Здесь надо бы научиться вызывать предыдущие команды... В Notebook я их пока не нашел, а надо бы...

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

In [32]:
 pdtemp
Out[32]:
Brandt 2014y 2013y 1413y 2014m 2013m 1413m Datem
0 Lada 36,513 40,011 -9% 283,802 343,368 -17% NaN
1 Renault* 15,406 17,254 -11% 139,434 155,081 -10% NaN
2 Hyundai* 15,398 17,171 -10% 132,849 135,609 -2% NaN
3 KIA 14,501 18,004 -19% 137,421 146,986 -7% NaN
4 Toyota* 13,067 13,715 -5% 115,589 115,146 0% NaN
5 Nissan* 11,844 15,002 -21% 114,389 101,965 12% NaN
6 VW 8,830 13,615 -35% 93,797 117,222 -20% NaN
7 Chevrolet 8,260 16,071 -49% 89,961 127,742 -30% NaN
8 Škoda 7,294 7,743 -6% 63,179 64,498 -2% NaN
9 Mitsubishi 6,304 6,451 -2% 52,462 56,240 -7% NaN
10 GAZ LCV* 5,705 7,910 -28% 48,180 60,873 -21% NaN
11 Ford* 5,268 8,120 -35% 44,938 77,474 -42% NaN
12 Opel 4,726 6,968 -32% 47,494 60,045 -21% NaN
13 Mercedes-Benz 4,336 4,264 2% 36,433 32,043 14% NaN
14 Mazda 4,031 4,320 -7% 35,280 31,462 12% NaN
15 UAZ* 3,667 3,897 -6% 30,121 36,895 -18% NaN
16 Audi 2,557 3,080 -17% 25,724 26,982 -5% NaN
17 BMW 2,400 4,434 -46% 26,317 29,692 -11% NaN
18 Daewoo 2,350 6,508 -64% 31,653 43,093 -27% NaN
19 SsangYong 1,977 3,288 -40% 17,464 25,738 -32% NaN
20 Lifan 1,930 2,594 -26% 15,842 19,323 -18% NaN
21 Lexus 1,902 1,418 34% 13,823 11,622 19% NaN
22 Land Rover 1,766 1,765 0% 15,419 14,774 4% NaN
23 Suzuki 1,461 2,454 -40% 13,755 21,783 -37% NaN
24 Honda 1,346 1,787 -25% 15,133 18,610 -19% NaN
25 Peugeot* 1,343 2,669 -50% 16,087 25,921 -38% NaN
26 Citroen* 1,295 2,400 -46% 14,988 21,731 -31% NaN
27 Geely 1,258 2,311 -46% 13,155 19,561 -33% NaN
28 Volvo 1,228 1,257 -2% 11,555 10,894 6% NaN
29 Chery 1,171 1,742 -33% 12,617 14,868 -15% NaN
... ... ... ... ... ... ... ... ...
35 Jeep 678 598 13% 5,768 3,438 68% NaN
36 Infiniti 639 768 -17% 5,921 6,443 -8% NaN
37 Datsun****** 520 - - 520 - - NaN
38 Porsche 232 294 -21% 3,079 2,726 13% NaN
39 Jaguar 138 157 -12% 1,246 1,247 0% NaN
40 Changan 120 - - 785 - - NaN
41 Haima 113 50 126% 606 237 156% NaN
42 Brilliance**** 107 - - 385 - - NaN
43 MINI 104 240 -57% 1,168 2,053 -43% NaN
44 SEAT 101 276 -63% 1,246 2,939 -58% NaN
45 Cadillac 101 101 0% 949 1,124 -16% NaN
46 Isuzu* 88 33 167% 396 131 202% NaN
47 BAW* 85 118 -28% 873 1,266 -31% NaN
48 JAC***** 64 - - 298 - - NaN
49 Acura** 64 - - 551 - - NaN
50 smart 42 28 50% 260 146 78% NaN
51 TagAZ* 15 28 -46% 125 339 -63% NaN
52 Alfa Romeo 9 - - 63 - - NaN
53 Chrysler 5 8 -38% 91 141 -35% NaN
54 Luxgen 2 - - 81 - - NaN
55 Vortex 0 5 - 0 928 - NaN
56 Foton* 0 0 0% 59 6 883% NaN
57 ZAZ 0 102 - 481 2,366 -80% NaN
58 BYD 0 0 0% 5 102 -95% NaN
59 Bogdan - 125 - 92 1,803 -95% NaN
60 Dodge******* - 13 - 26 174 -85% NaN
61 Izh 0 37 - 19 647 -97% NaN
62 FAW n/a 330 - 2,164 3,226 -33% NaN
63 cars 4,336 4,264 1.7% 36,433 32,043 13.7% NaN
64 vans 1,028 480 114.2% 5,617 3,422 64.1% NaN

65 rows × 8 columns

In [22]:
pdtemp = pd.read_csv(csvfile_path, error_bad_lines=False, names=COLNAMES, skiprows=0)
In [23]:
pdtemp.head()
Out[23]:
Brandt 2014y 2013y 1413y 2014m 2013m 1413m Datem
0 2014 2013 YoY % 2014 2013 YoY % NaN NaN
1 Lada 128633 151527 -15% 37030 44100 -16% NaN
2 Renault* 63647 67208 -5% 17395 19178 -9% NaN
3 KIA 60033 60027 0% 17744 18303 -3% NaN
4 Nissan* 57579 44188 30% 11835 8272 43% NaN

Вот у нас есть один заголовок таьлицы, мы его поменяем на другой. Однако, старый заголовок (строка) остается, если мы его не пропустим при считывании:

In [25]:
pdtemp = pd.read_csv(csvfile_path, error_bad_lines=False, names=COLNAMES, skiprows=1)
In [19]:
pdtemp.head()
Out[19]:
Brandt 2014y 2013y 1413y 2014m 2013m 1413m Datem
0 Lada 128633 151527 -15% 37030 44100 -16% NaN
1 Renault* 63647 67208 -5% 17395 19178 -9% NaN
2 KIA 60033 60027 0% 17744 18303 -3% NaN
3 Nissan* 57579 44188 30% 11835 8272 43% NaN
4 Hyundai* 57240 56582 1% 15933 15868 0% NaN
In [26]:
pdtemp.head()['Brandt']
Out[26]:
0        Lada
1    Renault*
2         KIA
3     Nissan*
4    Hyundai*
Name: Brandt, dtype: object
In [31]:
for csvfile in os.listdir(DIRPATH):
    if csvfile.startswith('eng_car-sales-in'):
        csvfile_path = os.path.join(DIRPATH, csvfile)
        
        pdtemp = pd.read_csv(csvfile_path, error_bad_lines=False, names=COLNAMES, skiprows=0)
        print (pdtemp.head())
     Brandt   2014y   2013y 1413y  2014m  2013m 1413m  Datem
0      2014    2013   YoY %  2014   2013  YoY %   NaN    NaN
1      Lada  128633  151527  -15%  37030  44100  -16%    NaN
2  Renault*   63647   67208   -5%  17395  19178   -9%    NaN
3       KIA   60033   60027    0%  17744  18303   -3%    NaN
4   Nissan*   57579   44188   30%  11835   8272   43%    NaN
     Brandt   2014y   2013y 1413y    2014m    2013m 1413m  Datem
0      Lada  26,467  39,079  -32%  247,289  303,357  -18%    NaN
1       KIA  13,644  17,013  -20%  122,920  128,982   -5%    NaN
2  Hyundai*  13,416  14,219   -6%  117,451  118,438   -1%    NaN
3   Toyota*  12,722  13,778   -8%  102,522  101,431    1%    NaN
4  Renault*  12,388  15,181  -18%  124,028  137,827  -10%    NaN
     Brandt   2014y   2013y 1413y    2014m    2013m 1413m  Datem
0      Lada  35,315  38,948   -9%  387,307  456,309  -15%    NaN
1       KIA  20,200  16,024   26%  195,691  198,018   -1%    NaN
2   Nissan*  20,131  17,540   15%  162,010  146,319   11%    NaN
3  Renault*  19,263  18,884    2%  194,531  210,099   -7%    NaN
4   Toyota*  17,536  14,742   19%  161,954  154,812    5%    NaN
     Brandt   2014y   2013y 1413y    2014m    2013m 1413m  Datem
0      Lada  28,014  37,549  -25%  220,822  264,278  -16%    NaN
1       KIA  15,303  17,099  -11%  109,276  111,969   -2%    NaN
2  Renault*  15,219  18,013  -16%  111,640  122,646   -9%    NaN
3  Hyundai*  14,461  14,753   -2%  104,035  104,219    0%    NaN
4   Toyota*  13,312  14,599   -9%   89,800   87,653    2%    NaN
     Brandt   2014y   2013y 1413y    2014m    2013m 1413m  Datem
0      Lada  30,114  37,177  -19%  192,808  226,729  -15%    NaN
1       KIA  17,023  17,541   -3%   93,973   94,870   -1%    NaN
2  Hyundai*  16,754  16,879   -1%   89,574   89,466    0%    NaN
3  Renault*  16,479  18,849  -13%   96,421  104,633   -8%    NaN
4   Toyota*  13,139  14,736  -11%   76,488   73,054    5%    NaN
     Brandt   2014y   2013y 1413y    2014m    2013m 1413m  Datem
0      Lada  34,061  38,025  -10%  162,694  189,552  -14%    NaN
1       KIA  16,917  17,302   -2%   76,950   77,329    0%    NaN
2  Renault*  16,295  18,576  -12%   79,942   85,784   -7%    NaN
3  Hyundai*  15,580  16,005   -3%   72,820   72,587    0%    NaN
4   Toyota*  13,189  13,708   -4%   63,349   58,318    9%    NaN
     Brandt   2014y   2013y 1413y    2014m    2013m 1413m  Datem
0      Lada  30,402  36,509  -17%  351,992  417,361  -16%    NaN
1       KIA  20,678  17,399   19%  175,491  181,994   -4%    NaN
2  Renault*  19,170  17,721    8%  175,268  191,215   -8%    NaN
3  Hyundai*  16,154  15,539    4%  164,396  166,982   -2%    NaN
4   Toyota*  15,952  12,093   32%  144,418  140,070    3%    NaN
     Brandt   2014y   2013y 1413y    2014m    2013m 1413m  Datem
0      Lada  37,788  37,484    1%  321,590  380,852  -16%    NaN
1       KIA  17,392  17,609   -1%  154,813  164,595   -6%    NaN
2  Renault*  16,664  18,413   -9%  156,098  173,494  -10%    NaN
3  Hyundai*  15,393  15,834   -3%  148,242  151,443   -2%    NaN
4   Toyota*  12,877  12,831    0%  128,466  127,977    0%    NaN
     Brandt   2014y   2013y 1413y    2014m    2013m 1413m  Datem
0      Lada  36,513  40,011   -9%  283,802  343,368  -17%    NaN
1  Renault*  15,406  17,254  -11%  139,434  155,081  -10%    NaN
2  Hyundai*  15,398  17,171  -10%  132,849  135,609   -2%    NaN
3       KIA  14,501  18,004  -19%  137,421  146,986   -7%    NaN
4   Toyota*  13,067  13,715   -5%  115,589  115,146    0%    NaN
In [ ]:
pdtemp[:3]
In [ ]:
 


Посты чуть ниже также могут вас заинтересовать

Комментариев нет:

Отправить комментарий