- PVSM.RU - https://www.pvsm.ru -
Для одного общественного проекта (визуализация бюджетов поселений и районов) мне потребовались данные об иерархии муниципальных образований и их численности.
Нужные данные я нашел [1], но форма их представления для корректного использования оставляла желать лучшего.
Все необходимые данные были в одном файле [2], однако, его форматирование затрудняло извлечение иерархии. Все названия муниципалитетов, районов и областей располагались в одном столбце и отличались только форматом ячейки и шрифта. Область выделялась жирным шрифтом, район — жирным наклонным, а поселение имело отступ. Также в файле находились несколько ошибок, например один район был выделен как область (или наоборот, уже не помню), а еще в одном месте в середине названия образования встретился переход строки (этот момент выяснился на этапе импорта в Google App Engine, когда db.StringProperty() ругнулся на multiline), исходный файл в этих местах пришлось исправить.
В поисках решения, как лучше это сделать, я набрел на библиотеку xlrd, возможностей которой хватает для этой задачи с лихвой. Подробнее о ней можно почитать тут [3], я же приведу код программы импорта и доступные параметры при работе с форматированием.
Форматирование ячейки и тип шрифта позволяют получить следующую информацию:
Со всеми параметрами я не разбирался, мне для данной задачи хватило типа шрифта и отступа (ident) в ячейке. Но видно, что возможности большие, вплоть до цвета конкретной границы ячейки или типа линии.
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import xlrd
import json
rb = xlrd.open_workbook('Tabl-35-12.xls', formatting_info=True)
font_list = rb.font_list # list of all fonts in excel table
sheet = rb.sheet_by_index(1)
rows_number = sheet.nrows
peoples_dict = {} # main dict
for rownum in range(7, rows_number): # data starts with line 7
cell = sheet.cell(rownum, 0)
value = cell.value.strip().replace('n', ' ') # delete spaces at start and end
peoples_count = sheet.cell(rownum, 1).value
if peoples_count == 0 or peoples_count == '': # empty row - continue
continue
peoples_count = int(peoples_count) # from 12313.0 to integer
cell_format = rb.xf_list[cell.xf_index]
current_font = font_list[cell_format.font_index]
bold = bool(current_font.bold)
italic = bool(current_font.italic)
indent = cell_format.alignment.indent_level
is_region = bold and not italic
is_raion = bold and italic
is_municipal = (indent == 2)
if is_region:
region = value
peoples_dict[region] = {'count': peoples_count}
elif is_raion:
raion = value
peoples_dict[region][raion] = {'count': peoples_count}
elif is_municipal:
municipal = value
peoples_dict[region][raion][municipal] = {'count': peoples_count}
print peoples_dict['Московская область']['Истринский муниципальный район']['Городское поселение Истра']['count']
with open('peoples.json', 'w') as outfile:
json.dump(peoples_dict, outfile)
В качестве бонуса — получившийся выходной файл, в формате json [4]. Структура — вложенные словари, где каждый элемент содержит ключ 'count', где записана численность образования, и ключи его потомков.
То есть численность Московской области можно получить так:
peoples_dict['Московская область']['count']
а численность города Истры Истринского муниципального района — так:
peoples_dict['Московская область']['Истринский муниципальный район']['Городское поселение Истра']['count']
Автор: KulikovPavel
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/36089
Ссылки в тексте:
[1] нашел: http://www.gks.ru/wps/wcm/connect/rosstat_main/rosstat/ru/statistics/publications/catalog/afc8ea004d56a39ab251f2bafc3a6fce
[2] в одном файле: https://github.com/Kulikovpavel/Excel-import/blob/master/Tabl-35-12.xls?raw=true
[3] тут: http://habrahabr.ru/post/99923/
[4] выходной файл, в формате json: https://github.com/Kulikovpavel/Excel-import/blob/master/peoples.json?raw=true
[5] Источник: http://habrahabr.ru/post/182548/
Нажмите здесь для печати.