В предыдущем посте мы создали файл, в котором склеены только девять месяцев 2014 года. А первых трех другой формат.
Здесь я попробовал тот же шаблон для февраля и марта.
Объект DataFrame (pdall) сформировался с ошибкамии -в столбцы попали данные разных форматов из-за ошибки парсера в строке *"Mercedes-Benz Vans","771","473","63%","459","279","65%",
** Потому этот подход показался неудобным, как и сам шаблон.
Сначала "ставим задачу", потом последовательно выполняем в итераторе импорт файлов со столбцами "Brandt 2014y 2013y 1413y 2014m 2013m 1413m Datem", добавляем столбец, читстим и преобразуем два столбца object в Float64, преобразуем строки в даты... Сохраняем все на диск и в инфо-файл.
01.Импортируем модули и библиотеки¶
import os
import pandas as pd
02. Зададим все константы в этом разделе (дописывать только сюда)¶
# Path to dir with files Must end with traling slash '/'
DIRPATH = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/feb1/'
# Insert my columns names in Dataframe objects
COLNAMES =['Brandt', '2014y', '2013y', '1413y', '2014m', '2013m', '1413m', 'Datem']
# Filter only filenames with
#filterfilenames = 'eng_car-sales-in'
# При считывании каждого файла во фрейм нужно будет добавлять столбец дат,
# для этого мы используем список и словарь:
months = ['january', 'febrary', 'march', 'april', 'may', 'jun',
'july', 'august','september', 'october','november', 'december']
dict = {'january':'31-1', 'february':'28-2', 'march':'31-1',
'april':'30-4', 'may':'31-5', 'june':'30-6',
'july':'31-7', 'august':'31-8','september':'30-9',
'october':'31-10','november':'30-11', 'december':'31-12'}
# Path to save dir for new fles Must end with traling slash '/'
#DIRPATH = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/1aug2/'
newpath = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new/'
#COLNAMES =['Brandt', '2014y', '2013y', '1413y', '2014m', '2013m', '1413m', 'Datem']
1. Выбор исходных данных. Рабочие папки с файлами, просмотрим и решим, что делать?¶
В предыдущем посте на эту тему мы закончили тем, что создали папку и записали в нее два файла, однако главный файл не записался. Потому из предыдущего поста убираем все лишнее, чтобы сделать шаблон для работы
!ls /media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new
# %load /media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new/2014_info.txt
resources folder: /media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv
filters: if csvfile.startswith filterfilenames = 'eng_car-sales-in'
concatent sourcefiles: 9
eng_car-sales-in-april-2014.csv
eng_car-sales-in-august-2014.csv
eng_car-sales-in-december-2014.csv
eng_car-sales-in-july-2014.csv
eng_car-sales-in-june-2014.csv
eng_car-sales-in-may-2014.csv
eng_car-sales-in-november-2014.csv
eng_car-sales-in-october-2014.csv
eng_car-sales-in-september-2014.csv
headers: COLNAMES =['Brandt', '2014y', '2013y', '1413y', '2014m', '2013m', '1413m', 'Datem']
results: newpath = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new/2014.txt'
help: [Первый рабочий пример конкатенции таблиц с преобразованием форматов столбцов object -> float]
http://pythonr.blogspot.ru/2015/04/object-float.html
weblog: http://pythonr.blogspot.com/2015/04/1-pandas-aerbu-2014.html
#Выберем два файла за февраль и март
!ls /media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/1feb
Как для них подобрать фильтр? Не могу сообразить, потому просто задам список:
listdir = ['/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/1feb/sales-in-february_2014_eng_final.csv',
'/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/1feb/sales-in-march_2014_eng_final.csv']
####2 Куда и как будем сохранять результаты
2.1 Подготовим информационный файл (вот в такой вид), но сохраним его в последнюю очередь.¶
# Don`t forget to create folder
!mkdir /media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new
Этот код запустить после всех исправелний и проверок. Сюда мы переходим после того, как сформирован и почищен объект pdall.
%%file /media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new/2014_2_3_info.txt
resources folder: /media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv
filters: if csvfile.startswith filterfilenames = 'eng_car-sales-in'
concatent sourcefiles: 2
'/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/1feb/'sales-in-february_2014_eng_final.csv',
'/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/1feb/sales-in-march_2014_eng_final.csv'
headers: COLNAMES =['Brandt', '2014y', '2013y', '1413y', '2014m', '2013m', '1413m', 'Datem']
results: newpath = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new/2014_2_3.txt'
help: [Первый рабочий пример конкатенции таблиц с преобразованием форматов столбцов object -> float]
http://pythonr.blogspot.ru/2015/04/object-float.html
weblog: http://pythonr.blogspot.com/2015/04/1-pandas-aerbu-2014.html
2.2 Проверим опции для сохранения объекта pdall в файл, но выполним код в ячейках в предпоследнюю очередь.¶
# Path to dir with files
#DIRPATH = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/1aug2/'
#newpath = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new'
# Columns in pdall
#COLNAMES =['Brandt', '2014y', '2013y', '1413y', '2014m', '2013m', '1413m', 'Datem']
print newpath
print COLNAMES
pdall.to_csv(newpath + '2014_2_3.txt',
sep=';',
#float_format='%.8f',
columns=COLNAMES,
index=False)
Итак, подготовка закончилась, начнем процесс обработки, потом снова вернемся к пп.2 и сохраним результаты¶
3. Просмотрим файлы в папке с исходными файлами и выберем подходящие¶
Сначала получим список файлов, его можно распечатать, а можно загнать в список(?) Чтобы потом легче было просмтривать здесь или вызывать.
#filelist =[]
for csvfile in listdir: #os.listdir(DIRPATH):
#if csvfile.startswith('eng_car-sales-in'):
print csvfile
# fullcsvfile = DIRPATH + csvfile
#filelist.append(fullcsvfile)
Тест: просмотреть файлы можно здесь (для этого надо раскомментировать три строки в коде выше)¶
Можно все просматривать старым дедовским способом - при помощи текстового редактора. Можно импортировать таблицу в объект DataFrame Pandas, но, как показывает опыт - объект может просто не открыться... , наконец, можно в цикле загрузить все в отдельную Notebook... из всех этих идей здесь пробуем вот такой вариант:
%load filelist['0']
4. Настроим фильтры для отбора исходных файлов в папке¶
Не надо забывать про проект правил, там все написано Проект соглашения с самим собой об обработки файлов таблиц AEBto3tables
Здесь можно проверять варианты фильтров, а константы надо записывать в начало поста, вот, что я уже использовал **# Filter only filenames with filterfilenames = 'eng_car-sales-in'** Этаконстанта есть в начале.
5. В процессе просмотра сюда копируем проблемные фрагмены¶
Фрагменты строк с проблемами для последующего планирования чистки
"Lada","54 543","66 947","-19%","30 896","36910","-16%",
"Renault*","29 615","30 040","-1%","16 721","15299","9%",
"Nissan*","28 209","22 051","28%","17 158","13126","31%",
Смотрим на строки... и планируем все действия. На первый раз я просто выделил два класса задач и записал только эту:
Сделать при импорте файла в DataFrame¶
Привести пропущенные значения, разделители тысяч, обозначить, что каждое значение в кавычках... можно в цикле считывания при импорте csv в один фрейм
# Заменить все "-", "n/a" одним Nan
# Убрать запятые- разделители разрядов "12,625" - coma
# Учесть, что каждое значение в кавычках '"'
Сделать обработку столбцов¶
- Добавить новый столбец даты, а дату взять из имени файла,
- Убрать в двух столбцах % и конвертировать значения в числа. При этом надо было проконтролироать отрицательные значения, не убрались ли "неодинокие" знаки "минус".
Далее мы возвращаемся к параметрам импорта¶
Соберем их здесь все вместе, пока не знаю точно, вставлять ли их в инфо-файл, но я чуть не забыл "В первом файле убрать строку заголовков !!!!! "
Часть имени для фильтра Да
Строки В первом файле убрать строку заголовков !!!!!
Количество строк Неодинаковое число строк в фалах
Пропуск плохихи строк error_bad_lines=False
Nan na_values=['-','n/a']
CSV quotechar='"', sep=',',
Разделитель разрядов thousands=','
6. Теперь каждый файл читаем в цикле и сначала распечатываем, что получилось, а потом осуществляем конкатенцию¶
# Для длинных файлов можно использовать такую печать
print (csvfile)
pdtemp.head(5)
print '...'
pdtemp.tail(3)
Поскольку это не боевой код, а скорее учебный, то я позволю себе такой убогий прием, как комментирование-раскомментирование строк. Комментари исправа омечают, как Раскоментировать для печати
Почему я документирую столь примитивный код? Потому, что в дальнейшем не хочу думать, надеюсь просто тупо выполнять элементарные действия.
6.0 Прежде, чем запускать это код надо выполнить метод addDatem() в ячейке под этой¶
Если сразу все не распечатается,то код используем для пофайловой отладки (печати)
#import pdb; pdb.set_trace() #Если раскоментировать, то можно испоьзовать паузы
pdall = pd.DataFrame()
for csvfile in listdir: #os.listdir(DIRPATH):
#if csvfile.startswith(filterfilenames):
csvfile_path = os.path.join(DIRPATH, csvfile)
pdtemp = pd.read_csv(csvfile_path, error_bad_lines=False, \
names=COLNAMES, na_values=['-','n/a'], \
quotechar='"', sep=',', thousands=' ')
pdtemp['Datem'] = addDatem(csvfile) #Закомментировать
pdall = pd.concat([pdall, pdtemp], ignore_index=True) #Закомментировать
#print (csvfile) #Раскомментировать
#print (pdtemp) #Раскомментировать
print(pdall) #Закомментировать
6.1. Тест: После того, как объект pdall сформирован, проверим визуально¶
# Как сформирован столбец дат, мы его сами слепили...
# Как осуществлена конкатенция
Для справки: метод addDatem()¶
def addDatem(csvfile):
# Parse month name from filename
namen = csvfile.split('-')[2].split('_')[0] # 'april' for example
# Replace strings with dict 'april':'30-4',
datstr = dict[namen] + '-2014' # '30-4-2014'
return datstr
Для справки: Тест для addDatem. Можно проверить, как все работает¶
csvfilet = 'sales-in-february_2014_eng_final.csv' #'eng_car-sales-in-april-2014.csv'
addDatem(csvfile)
7 Выполнить только если использовал выше дебаггер и хочешь сохранить его записи выше.¶
Точнее, если выше пришлось изменить код и печатать исходные файлы, а не создавать обект pdall, то здесь создадим и распечатаем этот pdall.
#import pdb; pdb.set_trace() #Если раскоментировать, то можно испоьзовать паузы
pdall = pd.DataFrame()
for csvfile in os.listdir(DIRPATH):
if csvfile.startswith(filterfilenames):
csvfile_path = os.path.join(DIRPATH, csvfile)
pdtemp = pd.read_csv(csvfile_path, error_bad_lines=False, \
names=COLNAMES, na_values=['-','n/a'], \
quotechar='"', sep=',', thousands=',')
pdtemp['Datem'] = addDatem(csvfile) #Закомментировать
pdall = pd.concat([pdall, pdtemp], ignore_index=True) #Закомментировать
#print (csvfile) #Раскомментировать
#print (pdtemp) #Раскомментировать
print(pdall) #Закомментировать
####Итак, все исходные файлы теперь в одном объекте. начнем чистить и преобразовывать столбцы
8. Удалить '%' и сменить формат на числовой (Важно! )¶
У нас осталось две строки процентов, надо убрать из них знаки "%" и перевести в формат float
ИЗ Python for Data Analysis
Часть данных имеет вид целых, а в части есть 888.555 точка. В процессе предыдущих экспериментов я пытался все перевести в формат Int, но мне не попадались дроби..., только посмотрев (распечатав выше) все данные, понял, почему выскакивала ошибка.
Так что просто выполним код:
pdall['1413y'] = pdall['1413y'].str.replace('%','').astype(float)
pdall['1413m'] = pdall['1413m'].str.replace('%','').astype(float)
Тест Важно! тип столбцов должен быть "float64" (а был "object")¶
pdall.info(verbose=True, buf=None, max_cols=None, memory_usage=True, null_counts=True)
Почему "2014m 116 non-null object" ...?... смотрим внимательно на распечатку столбцов. Ага, там пробел в качестве разделителя разрядов.
9. Пробуем убрать пробелы в столбце и конвертировать строки в числа¶
И вот, что происходит, если в столбец попадает не числовой, а строковый элемент (36). Обратите внимвние, после того, как строковый элемент в столбце "пройден", команда смены типа проходит. В нижней части столбца пробелов нет, а в вверхней есть.
# Тест
pdall['2014y'][0:3].str.replace(' ','').astype(float)
pdall['2014y'][30:85]
Распечатаем строку с ошибкой¶
Очевидно, что это последствие ошибки парсера, который разделил "Mercedes-Benz", "Vans*",... и все сдвинулось...
pdall.ix[35:37]
Просто исправим ошибку в исходном файле *"Mercedes-Benz Vans","771","473","63%","459","279","65%", ** и перезапустим итератор, проверка типов показала, что теперь все в норме. Снова выполняем:
pdall['1413y'] = pdall['1413y'].str.replace('%','').astype(float)
pdall['1413m'] = pdall['1413m'].str.replace('%','').astype(float)
На этот раз ошибки нет. Посмотрим типы данных в столбцах
pdall.info(verbose=True, buf=None, max_cols=None, memory_usage=True, null_counts=True)
II Если мы хотим редактировать или использовать столбец дат¶
И нам нужно, чтобы столбец строк, который мы добавили в объект читался, как столбец дат... то можно использовать метод .to_datetime
#### Тест: Конвертация строки в объект даты
pd.to_datetime(pdall.Datem).tail() # == pd.to_datetime(pd001['Datem'])
II.1 Теперь можно изменить столбец Datem (осторожно, лучше просто создать копию !!!):¶
pdall.Datem = pd.to_datetime(pdall.Datem) #pd.Datem(pd001.dat) # == pd.to_datetime(pd001['dat'])
Если мы записываем промежуточный файл, то менять формат категорически не рекомендуется. Мы можем забыть, что что-то изменили...
III Проверка результатов (перед сохранением в файл)¶
Осталось проверить trailing spaces, но Pandas за такимим мелочами следит сам (в чем я не уверен)
III Тест_1: Визуальный контроль фрагментов¶
pdall.head(), pdall[30:40], pdall.tail(5)
III Тест_2: Контроль форматов столбцов¶
pdall.info(verbose=True, buf=None, max_cols=None, memory_usage=True, null_counts=True)
Осталось только сохранить объект Dateframe в файл¶
Для это не мешкая вернемся к пп.2 обязательно проверим, отредактируем параметры записи и запишем два файла: Сначала сохраним объект pdall в файл csv, Потом запишем информационный файл.
Посты чуть ниже также могут вас заинтересовать
Комментариев нет:
Отправить комментарий