"Третьи таблицы" - это таблицы, в которых приведены 25 самых продаваемых марок автомобилей. В 2014 году формат таблиц поменяли в июле. Открываешь папку, там имена всех файлов имеют одинаковый префикс, естественно, хочется запихнуть в DataFran (pdall) все файлы сразу. Но при распечатывании фрагментов padll обнаруживается "перемешивание столбцов". Здесь я "нашел" способ распечатать фрагменты из каждого файла. И понимаешь, что надо контролировать содержимое каждого файла перед загрузкой (в редакторе, хе-хе...). Потом понимаешь, что прежде, чем писать (предварительный прсмотр) загрузчик надо бы понять, как это нужно делать именно с Pandas... Польза от поста: можно понять, как до меня доходила простая идея о том, что можно сначала все просто загрузить в один фрейм, а потом из него фильтровать одинаковые форматы...
[IO Tools (Text, CSV, HDF5, ...)]|(http://pandas.pydata.org/pandas-docs/dev/io.html?highlight=dateutil)
Step-by-step debugging with IPython
Stepping into a function in IPython ipdb.runcall(foo, 1, 2)
26.2. pdb — The Python Debugger
Python for Data Analysis 2012.pdf
Очевидно, что третья таблица понадобится. Сразу состыкуем ее с первой.¶
Сразу же скопируем ячейки с данными первой таблицы, нам нужно проанализировать содержание столбцов их имена должны соответствовать
# Это копипаст из первой таблицы ДЛЯ СПРАВКИ
# Path to dir with files Must end with traling slash '/'
#DIRPATH = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new/'
# Insert my columns names in Dataframe objects
#COLNAMES =['Brandt', '2014y', '2013y', '1413y', '2014m', '2013m', '1413m', 'Datem']
RUN: Опреднлим путь к исходным файлам для третьей таблицы¶
DIRPATH = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/3aug2/'
#### Теперь проанализируем содержание файлов
# Это фрагмент из первой таблицы
"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%",
####Здесь в каждом файле по 25 строк
Нам нужно определить, какие столбцы в двух шаблонах совпадают, и составить новый список заголовков.
# Это фрагменты из третьей таблицы
"1","Granta","Lada","45570","52765","(7,195)","-14%","13077","15596","(2,519)","-16%",
"2","Solaris","Hyundai","35218","35941","(723)","-2%","9774","10553","(779)","-7%",
"3","New Rio","KIA","29971","28211","1,760","6%","9045","8430","615","7%",
...
"23","Juke","Nissan","9589","7750","1,839","24%","2837","1657","1,180","71%",
"24","Outlander","Mitsubishi","9447","8015","1,432","18%","1526","2447","(921)","-38%",
"25","X-Trail","Nissan","9177","8767","410","5%","1436","1614","(178)","-11%",
# 25 BEST SOLD MODELS OF CARS IN RUSSIA FOR
# JANUARY - APRIL 2014/2013 AND APRIL 2014/2013
# (Data submitted by the AEB Automobile Manufacturers Committee; retail sales of imported and locally produced vehicles)
Особенности исходных данных¶
Злдесь встречаемся с новым способом записи отрицательных чисел
"1","Granta","Lada","45570","52765","(7,195)","-14%","13077","15596","(2,519)","-16%",
Запятая, разделяющая тысячи внутри клруглых скобок. Вот почему у меня депрессия, каждый раз какое-нибудь нововведние... В доументации не нашел опции для скобок... попробуем применить .str.replace(...).astype()
RUN: Названия столбцов для третьего шаблона(3) csv файла данных "aerbu"¶
# Insert my columns names in Dataframe objects
COLNAMES =['Model', 'Brandt', \
'2014y3', '2013y3', 'u1413y3', '1413y3', \
'2014m3', '2013m3', 'u1413m3', '1413m3', 'Datem']
Здесь самое время порассуждать о том, как называть столбцы. С одной стороны, данные имеют тот же "физический смысл", что и в первой таблице. Сначала суммарные столбцы за год, потом помесячные продажи. Так что, нет смысла переименовывать столбцы.
С другой стороны, если я захочу (вдруг) слить каким-либо образом два вида таблиц, то с одинаковыми заголовками столбцов могут возникнуть проблемы..., даже, если я просто открою пару файлов в которых есть строки заголовков, то могу решить, что эти данные можно стравнивать...
Так что, чтобы не думать, проще вставить один символ, например "3" в заголовки столбцов данных. И далее руководствоваться простым правилом - Столбцы с одинаковыми именами из разгных таблиц могут быть ключевыми
RUN: Оставшиеся исходные данные¶
# При считывании каждого файла во фрейм нужно будет добавлять столбец дат,
# для этого мы используем список и словарь:
months = ['january', 'february', 'march', 'april', 'may', 'june',
'july', 'august','september', 'october','november', 'december']
dict = {'january':'31-1', 'february':'28-2', 'march':'31-3',
'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'}
RUN: Сформируем список исходных файлов¶
!ls '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/3aug2/' -hl
Поскольку приходится парсить имя файла, чтобы вытащить название месяца, то поступим так же, как и с первой таблицей. Начнем с фильтра
filterfilenames = 'eng_car-sales-in'
RUN: Теперь решим, куда все это сохранять¶
# Don`t forget to create folder
!mkdir /media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new/3tab
%%file /media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new/3tab/2014_info.txt
resources folder: /media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv/3aug2/
filters: if csvfile.startswith filterfilenames = 'eng_car-sales-in'
concatent sourcefiles: 9
-rw-r--r-- 1 kiss kiss 2.1K Feb 20 21:12 eng_car-sales-in-april-2014.csv
-rw-r--r-- 1 kiss kiss 2.4K Feb 20 21:12 eng_car-sales-in-august-2014.csv
-rw-r--r-- 1 kiss kiss 2.4K Feb 20 21:12 eng_car-sales-in-december-2014.csv
-rw-r--r-- 1 kiss kiss 2.4K Feb 20 21:12 eng_car-sales-in-july-2014.csv
-rw-r--r-- 1 kiss kiss 2.2K Feb 20 21:12 eng_car-sales-in-june-2014.csv
-rw-r--r-- 1 kiss kiss 2.1K Feb 20 21:12 eng_car-sales-in-may-2014.csv
-rw-r--r-- 1 kiss kiss 2.4K Feb 20 21:12 eng_car-sales-in-november-2014.csv
-rw-r--r-- 1 kiss kiss 2.0K Feb 20 21:12 eng_car-sales-in-october-2014.csv
-rw-r--r-- 1 kiss kiss 2.4K Feb 20 21:12 eng_car-sales-in-september-2014.csv
headers: COLNAMES =['Model', 'Brandt', \
'2014y3', '2013y3', 'u1413y3', '1413y3', \
'2014m3', '2013m3', 'u1413m3', '1413m3', 'Datem']
results: newpath = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new/3tab/2014.csv'
help: [Первый рабочий пример конкатенции таблиц с преобразованием форматов столбцов object -> float]
http://pythonr.blogspot.ru/2015/04/object-float.html
weblog: http://pythonr.blogspot.com/2015/04/3-aerbu.html
Сюда мы возвращаемся после того, как сформирован и почищен объект pdall¶
newpath = '/media/MYLINUXLIVE/Documents/Xpdf/aerbu_2014_all_csv_new/3tab/2014.csv'
print COLNAMES
pdall.to_csv(newpath + '2014.csv',
sep=';',
#float_format='%.8f',
columns=COLNAMES,
index=False)
Формируем объект pdall¶
RUN: Для справки: метод addDatem() инициализировать до запуска итератора¶
def addDatem(csvfile):
# Parse month name from filename
namen = csvfile.split('-')[3] # 'april' for example
# Replace strings with dict 'april':'30-4',
datstr = dict[namen] + '-2014' # '30-4-2014'
return datstr
RUN: Протестируем, как работает addDatem().¶
csvfile = 'eng_car-sales-in-april-2014.csv'
addDatem(csvfile)
RUN: Импортируем Pandas и OS¶
import os
import pandas as pd
RUN: Запускаем итератор¶
#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) #Закомментировать
Впечатление такое, что с мая в исходных файлах был изменен порядок столбцов. Так что надо посмотерь исходник (pdf)
#eng_car-sales-in-august-2014.csv
"1","Granta","Lada","11,860","14,951","(3,091)","1","Granta","Lada","95,154","113,738","(18,584)",
"2","Solaris","Hyundai","9,086","8,590","496","2","Solaris","Hyundai","74,438","75,081","(643)",
"3","New Rio","KIA","5,999","7,159","(1,160)","3","New Rio","KIA","60,032","59,046","986",
...
"24","Patriot","UAZ","1,963","1,427","536","24","Astra","Opel","16,539","26,346","(9,807)",
"25","CX-5","Mazda","1,790","1,789","1","25","CX-5","Mazda","15,047","11,575","3,472",
# eng_car-sales-in-may-2014.csv
"1","Lada","Granta","12,947","14,471","-1,524","-11%","58,517","67,236","-8,719","-13%",
"2","Hyundai","Solaris","9,791","10,493","-702","-7%","45,009","46,434","-1,425","-3%",
"3","KIA","New Rio","8,513","7,978","535","7%","38,484","36,189","2,295","6%",
...
"24","Mitsubishi","Outlander","1,469","1,812","-343","-19%","10,916","9,827","1,089","11%",
"25","Nissan","Juke","1,242","2,111","-869","-41%","10,831","9,861","970","10%",
Итак, мы видим, что файлы считываются в алфавитном порядке... и выше мы получили отличный пример "перемешивания столбцов".
Очевидно, в данном случае алгоритмы пакетной обработки файлов в папке вообще не подходят. Одна настройка чего стоит. Проще перебрать файлы вручную. Так и поступим.
Но для этого нужно уметь:¶
0. Читать все столбцы
1. Переставлят столбцы
2. Переименовывать столбцы
3. Дописывать столбцы в файл
Хорошо, что не написал сразу "в Pandas"... пожалуй, переставлять проще, а все остальное под вопросом... Потому в учебных целях будем все делать двумя способами... Преимущество оставим за Padas, поскольку мы должны быть уверены, что итоговые файлы Padas откроет...
filen = []
for csvfile in os.listdir(DIRPATH):
filen.append(DIRPATH + csvfile)
#filename = DIRPATH + 'eng_car-sales-in-may-2014.csv'
filename = filen[5]
with open(filename, 'r') as f:
print(filename.split('/')[-1])
print( '---')
print(f.readline())
names=COLNAMES,
#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, \
na_values=['-','n/a'], \
quotechar='"', sep=',', thousands=',')
#pdtemp['Datem'] = addDatem(csvfile) #Закомментировать
#pdall = pd.concat([pdall, pdtemp], ignore_index=True) #Закомментировать
#pd.set_option('display.max_columns'= 9, False)
pd.set_option('display.width', 1000)
print (csvfile)
print (len(pdtemp.columns))
print (pdtemp).head(3)
print (pdtemp).tail(2)
#pdtemp.info()
print (' ')
#print(pdall) #Закомментировать
COLNAMES_0_11 =['Model', 'Brandt', \
'2014y3', '2013y3', 'u1413y3', '1413y3', \
'2014m3', '2013m3', 'u1413m3', '1413m3', 'Datem']
pdall011 = pd.DataFrame(columns=COLNAMES_0_11)
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_0_11, na_values=['-','n/a'], \
quotechar='"', sep=',', thousands=',')
if pdtemp.columns[''] == 12:
#pdtemp['Datem'] = addDatem(csvfile)
print (csvfile)
print (len(pdtemp.columns))
print (pdtemp).head(3)
print (pdtemp).tail(2)
#pdtemp.info()
print (' ')
pdall011 = pd.concat([pdall011, pdtemp], ignore_index=True)
pd.set_option('display.width', 1000)
pdall011.shape, ' number of rows: ' ,pdall011.shape[0],' or: ', len(pdall011.index)
pdtemp.shape, ' number of columns: ' ,pdtemp.shape[1],' or: ', len(pdtemp.columns)
pdtemp.icol(0), pdtemp.irow(0)
pdall011.shape
pdall011.icol(0).name
pdtemp.columns.get_loc("Model") # Номер столбца по имени
pdtemp.info
pdtemp.info()
pdtemp.dtypes
pdtemp.icol(0)
pdtemp.index
col0 = pdtemp.icol(0)
col0.get_dtype_counts
col0.get_dtype_counts()
Ох уж это этот апрель! Оказывается, столбцы переставляли как минимум два раза - в мае и июне.
Отметим между делом, что в одних и тех же столбцах есть и знаки минус и скобки, эти столбцы скорее всего будут прочитаны, как строуовые...
Посты чуть ниже также могут вас заинтересовать
Комментариев нет:
Отправить комментарий