Особо представлять базу ФИАС нет необходимости:

Скачать ее можно перейдя по ссылке, данная база является открытой и содержит все адреса объектов по России (адресный реестр). Интерес к этой базе вызван тем, что файлы, которые в ней содержатся достаточно объемны. Так, например, самый маленький составляет 2,9 Гб. Предлагается остановиться на нем и посмотреть, справится ли с ним pandas, если работать на машине, располагая только 8 Гб оперативной памяти. А если не справится, какие есть опции, для того, чтобы скормить pandas данный файл.
Положа руку на сердце, не разу не сталкивался с данной базой и это дополнительное препятствие, т.к. абсолютно не ясен формат данных, представленных в ней.
Скачав архив fias_xml.rar с базой, достанем из него файл — AS_ADDROBJ_20190915_9b13b2a6-b3bd-4866-bd1c-7ab966fafcf0.XML. Файл имеем формат xml.
Для более удобной работы в pandas рекомендуется конвертировать xml в csv или json.
Однако все попытки конвертации сторонними программами и самим python приводят к ошибке «MemoryError» либо зависанию.
Хм. Что, если разрезать файл и частями конвертировать? Хорошая идея, но все «резчики» также пытаются считать файл в память целиком и виснут, не режет его и сам python, идущий по пути «резчиков». 8 Гб явно маловато? Что ж, посмотрим.
Придется воспользоваться сторонней программой vedit.
Данная программа позволяет считать файл xml размером 2,9 Гб и поработать с ним.
Также она позволяет его разделить. Но тут есть небольшая хитрость.
Как видно при считывании файла, в нем, помимо прочего, есть открывающий тег AddressObjects:

Значит, создавая части данного большого файла, надо не забывать его(тег) закрывать.
То есть начало каждого xml файла будет таким:
а окончание:
Теперь отрежем первую часть файла (для остальных частей шаги те же).
В программе vedit:

Далее выбираем Goto и Line#. В открывшемся окне пишем номер строки, например 1000000:

Далее надо подкорректировать выделенный блок, чтобы он захватил до конца объект в базе до закрывающего тега:

Ничего страшного, если будет небольшой нахлест на последующий объект.
Далее в программе vedit сохраняем выделенный фрагмент — File, Save as.
Таким же способом создаем остальные части файла, помечая начало блока выделения и окончание с шагом 1млн строк.
В итоге должно получиться 4-е xml файла размером примерно по 610 Мб.
Теперь надо во вновь созданных файлах xml добавить теги, чтобы они читались как xml.
Откроем поочередно файлы в vedit и добавим в начале каждого файла:
и в конце:
Таким образом, теперь у нас 4 xml части разделенного первоначального файла.
Теперь переведем xml в csv, написав программу на python.
Код программы
С помощью программы надо конвертировать все 4-е файла в csv.
Размер файлов уменьшится, каждый будет по 236 Мб (сравните с 610 Мб в xml).
В принципе, теперь с ними уже можно работать, через excel или notepad++.
Однако файлов пока 4-е вместо одного, и мы не добрались до цели — обработка файла в pandas.
В Windows это может оказаться непростым занятием, поэтому воспользуемся консольной утилитой на python, которая называется csvkit. Устанавливается как модуль python:
*На самом деле это целый набор утилит, но оттуда потребуется одна.
Зайдя в папку с файлами для склейки в консоли, выполним склейку в один файл. Так как все файлы без заголовков, то назначим при склейке стандартные названия столбцов: a,b,c и т.д.:
На выходе получаем готовый csv файл.
Если сразу загрузить в pandas файл
и проверить сколько он займет памяти, результат может неприятно удивить:

3 Гб! И это при том, что при считывании данных первый столбец «пошел» в качестве индекс-столбца*, а так объем был бы еще больше.
*По умолчанию pandas задает свой индекс-столбец.
Проведем оптимизацию, используя методы из предыдущего поста и статьи:
— object в category;
— int64 в uint8;
— float64 в float32.
Для этого при считывании файла добавим dtypes и считывание столбцов в коде будет выглядеть так:
Теперь, открыв файл pandas использование памяти будет разумным:

Осталось добавить в csv файл, при желании, строку-фактические названия столбцов, чтобы данные обрели смысл:
*Этой строкой можно заменить названия столбцов, но тогда придется поменять код.
Сохраним первые строки файла из pandas
и посмотрим, что получилось в excel:

Код программы для оптимизированного открытия csv файла с базой:
В завершение посмотрим размер датасета:
3,3 млн строк, 28 столбцов.
Итог: при первоначальном объеме файла csv 890 Мб, «оптимизированный» для целей работы с pandas он занимает в памяти 1,2 Гб.
Таким образом, при грубом расчете можно предположить что файл размером 7,69 Гб можно будет открыть в pandas, предварительно его «оптимизировав».

Скачать ее можно перейдя по ссылке, данная база является открытой и содержит все адреса объектов по России (адресный реестр). Интерес к этой базе вызван тем, что файлы, которые в ней содержатся достаточно объемны. Так, например, самый маленький составляет 2,9 Гб. Предлагается остановиться на нем и посмотреть, справится ли с ним pandas, если работать на машине, располагая только 8 Гб оперативной памяти. А если не справится, какие есть опции, для того, чтобы скормить pandas данный файл.
Положа руку на сердце, не разу не сталкивался с данной базой и это дополнительное препятствие, т.к. абсолютно не ясен формат данных, представленных в ней.
Скачав архив fias_xml.rar с базой, достанем из него файл — AS_ADDROBJ_20190915_9b13b2a6-b3bd-4866-bd1c-7ab966fafcf0.XML. Файл имеем формат xml.
Для более удобной работы в pandas рекомендуется конвертировать xml в csv или json.
Однако все попытки конвертации сторонними программами и самим python приводят к ошибке «MemoryError» либо зависанию.
Хм. Что, если разрезать файл и частями конвертировать? Хорошая идея, но все «резчики» также пытаются считать файл в память целиком и виснут, не режет его и сам python, идущий по пути «резчиков». 8 Гб явно маловато? Что ж, посмотрим.
Программа Vedit
Придется воспользоваться сторонней программой vedit.
Данная программа позволяет считать файл xml размером 2,9 Гб и поработать с ним.
Также она позволяет его разделить. Но тут есть небольшая хитрость.
Как видно при считывании файла, в нем, помимо прочего, есть открывающий тег AddressObjects:

Значит, создавая части данного большого файла, надо не забывать его(тег) закрывать.
То есть начало каждого xml файла будет таким:
<?xml version="1.0" encoding="utf-8"?><AddressObjects>
а окончание:
</AddressObjects>
Теперь отрежем первую часть файла (для остальных частей шаги те же).
В программе vedit:

Далее выбираем Goto и Line#. В открывшемся окне пишем номер строки, например 1000000:

Далее надо подкорректировать выделенный блок, чтобы он захватил до конца объект в базе до закрывающего тега:

Ничего страшного, если будет небольшой нахлест на последующий объект.
Далее в программе vedit сохраняем выделенный фрагмент — File, Save as.
Таким же способом создаем остальные части файла, помечая начало блока выделения и окончание с шагом 1млн строк.
В итоге должно получиться 4-е xml файла размером примерно по 610 Мб.
Доработаем xml-части
Теперь надо во вновь созданных файлах xml добавить теги, чтобы они читались как xml.
Откроем поочередно файлы в vedit и добавим в начале каждого файла:
<?xml version="1.0" encoding="utf-8"?><AddressObjects>
и в конце:
</AddressObjects>
Таким образом, теперь у нас 4 xml части разделенного первоначального файла.
Xml-to-csv
Теперь переведем xml в csv, написав программу на python.
Код программы
здесь
.# -*- coding: utf-8 -*- from __future__ import unicode_literals import codecs,os import xml.etree.ElementTree as ET import csv from datetime import datetime parser = ET.XMLParser(encoding="utf-8") tree = ET.parse("add-30-40.xml",parser=parser) root = tree.getroot() Resident_data = open('fias-30-40.csv', 'w',encoding='UTF8') csvwriter = csv.writer(Resident_data) start = datetime.now() for member in root.findall('Object'): object = [] object.append(member.attrib['AOID']) object.append(member.attrib['AOGUID']) try: object.append(member.attrib['PARENTGUID']) except: object.append(None) try: object.append(member.attrib['PREVID']) except: object.append(None) #try: # object.append(member.attrib['NEXTID']) #except: # object.append(None) object.append(member.attrib['FORMALNAME']) object.append(member.attrib['OFFNAME']) object.append(member.attrib['SHORTNAME']) object.append(member.attrib['AOLEVEL']) object.append(member.attrib['REGIONCODE']) object.append(member.attrib['AREACODE']) object.append(member.attrib['AUTOCODE']) object.append(member.attrib['CITYCODE']) object.append(member.attrib['CTARCODE']) object.append(member.attrib['PLACECODE']) object.append(member.attrib['STREETCODE']) object.append(member.attrib['EXTRCODE']) object.append(member.attrib['SEXTCODE']) try: object.append(member.attrib['PLAINCODE']) except: object.append(None) try: object.append(member.attrib['CODE']) except: object.append(None) object.append(member.attrib['CURRSTATUS']) object.append(member.attrib['ACTSTATUS']) object.append(member.attrib['LIVESTATUS']) object.append(member.attrib['CENTSTATUS']) object.append(member.attrib['OPERSTATUS']) try: object.append(member.attrib['IFNSFL']) except: object.append(None) try: object.append(member.attrib['IFNSUL']) except: object.append(None) try: object.append(member.attrib['OKATO']) except: object.append(None) try: object.append(member.attrib['OKTMO']) except: object.append(None) try: object.append(member.attrib['POSTALCODE']) except: object.append(None) #print(len(object)) csvwriter.writerow(object) Resident_data.close() print(datetime.now()- start) #0:00:21.122437
С помощью программы надо конвертировать все 4-е файла в csv.
Размер файлов уменьшится, каждый будет по 236 Мб (сравните с 610 Мб в xml).
В принципе, теперь с ними уже можно работать, через excel или notepad++.
Однако файлов пока 4-е вместо одного, и мы не добрались до цели — обработка файла в pandas.
Склеим файлы в один
В Windows это может оказаться непростым занятием, поэтому воспользуемся консольной утилитой на python, которая называется csvkit. Устанавливается как модуль python:
pip install csvkit
*На самом деле это целый набор утилит, но оттуда потребуется одна.
Зайдя в папку с файлами для склейки в консоли, выполним склейку в один файл. Так как все файлы без заголовков, то назначим при склейке стандартные названия столбцов: a,b,c и т.д.:
csvstack -H fias-0-10.csv fias-10-20.csv fias-20-30.csv fias-30-40.csv > joined2.csv
На выходе получаем готовый csv файл.
Поработаем в pandas над оптимизацией использования памяти
Если сразу загрузить в pandas файл
import pandas as pd import numpy as np gl = pd.read_csv('joined2.csv',encoding='ANSI',index_col='a') print (gl.info(memory_usage='deep')) # использование памяти def mem_usage(pandas_obj): if isinstance(pandas_obj,pd.DataFrame): usage_b = pandas_obj.memory_usage(deep=True).sum() else: # предположим, что если это не датафрейм, то серия usage_b = pandas_obj.memory_usage(deep=True) usage_mb = usage_b / 1024 ** 2 # преобразуем байты в мегабайты return "{:03.2f} МВ" .format(usage_mb)
и проверить сколько он займет памяти, результат может неприятно удивить:

3 Гб! И это при том, что при считывании данных первый столбец «пошел» в качестве индекс-столбца*, а так объем был бы еще больше.
*По умолчанию pandas задает свой индекс-столбец.
Проведем оптимизацию, используя методы из предыдущего поста и статьи:
— object в category;
— int64 в uint8;
— float64 в float32.
Для этого при считывании файла добавим dtypes и считывание столбцов в коде будет выглядеть так:
gl = pd.read_csv('joined2.csv',encoding='ANSI',index_col='a', dtype ={ 'b':'category', 'c':'category','d':'category','e':'category', 'f':'category','g':'category', 'h':'uint8','i':'uint8','j':'uint8', 'k':'uint8','l':'uint8','m':'uint8','n':'uint16', 'o':'uint8','p':'uint8','q':'uint8','t':'uint8', 'u':'uint8','v':'uint8','w':'uint8','x':'uint8', 'r':'float32','s':'float32', 'y':'float32','z':'float32','aa':'float32','bb':'float32', 'cc':'float32' })
Теперь, открыв файл pandas использование памяти будет разумным:

Осталось добавить в csv файл, при желании, строку-фактические названия столбцов, чтобы данные обрели смысл:
AOID,AOGUID,PARENTGUID,PREVID,FORMALNAME,OFFNAME,SHORTNAME,AOLEVEL,REGIONCODE,AREACODE,AUTOCODE,CITYCODE,CTARCODE,PLACECODE,STREETCODE,EXTRCODE,SEXTCODE,PLAINCODE,CODE,CURRSTATUS,ACTSTATUS,LIVESTATUS,CENTSTATUS,OPERSTATUS,IFNSFL,IFNSUL,OKATO,OKTMO,POSTALCODE
*Этой строкой можно заменить названия столбцов, но тогда придется поменять код.
Сохраним первые строки файла из pandas
gl.head().to_csv('out.csv', encoding='ANSI',index_label='a')
и посмотрим, что получилось в excel:

Код программы для оптимизированного открытия csv файла с базой:
код
import os import time import pandas as pd import numpy as np #используем оптимизацию памяти при считывании датафрейма: для object-category,для float64-float32,для int64-int gl = pd.read_csv('joined2.csv',encoding='ANSI',index_col='a', dtype ={ 'b':'category', 'c':'category','d':'category','e':'category', 'f':'category','g':'category', 'h':'uint8','i':'uint8','j':'uint8', 'k':'uint8','l':'uint8','m':'uint8','n':'uint16', 'o':'uint8','p':'uint8','q':'uint8','t':'uint8', 'u':'uint8','v':'uint8','w':'uint8','x':'uint8', 'r':'float32','s':'float32', 'y':'float32','z':'float32','aa':'float32','bb':'float32', 'cc':'float32' }) pd.set_option('display.notebook_repr_html', False) pd.set_option('display.max_columns', 8) pd.set_option('display.max_rows', 10) pd.set_option('display.width', 80) #print (gl.head()) print (gl.info(memory_usage='deep')) # использование памяти def mem_usage(pandas_obj): if isinstance(pandas_obj,pd.DataFrame): usage_b = pandas_obj.memory_usage(deep=True).sum() else: # предположим, что если это не датафрейм, то серия usage_b = pandas_obj.memory_usage(deep=True) usage_mb = usage_b / 1024 ** 2 # преобразуем байты в мегабайты return "{:03.2f} МВ" .format(usage_mb)
В завершение посмотрим размер датасета:
gl.shape
(3348644, 28)
3,3 млн строк, 28 столбцов.
Итог: при первоначальном объеме файла csv 890 Мб, «оптимизированный» для целей работы с pandas он занимает в памяти 1,2 Гб.
Таким образом, при грубом расчете можно предположить что файл размером 7,69 Гб можно будет открыть в pandas, предварительно его «оптимизировав».
