CoderCastrov logo
CoderCastrov
Питон

Парсинг базы данных Всемирных индикаторов развития (ВИР) с использованием Python

Парсинг базы данных Всемирных индикаторов развития (ВИР) с использованием Python
просмотров
4 мин чтение
#Питон

В этой статье представлено пошаговое руководство по созданию функции на Python, которая использует пакет xmltree для парсинга и обработки последних данных из базы данных ВИР для нескольких серий одновременно.

База данных Всемирных индикаторов развития, поддерживаемая Всемирным банком, является одной из самых мощных и разнообразных баз данных с открытым доступом. База данных содержит наборы данных по широкому спектру развития и является аналитическим золотым рудником для всех, кто интересуется исследованием развития как количественно, так и качественно.

Лично я часто полагался на эту базу данных как во время своей научно-исследовательской работы в качестве аспиранта, так и во время своей карьеры ученого. В этой статье я предоставляю пошаговое руководство по скрипту, который парсит наборы данных из базы данных ВИР и сохраняет их в виде фрейма данных. Скрипт использует библиотеку xmltree на Python и очень эффективен в парсинге последних доступных данных из базы данных ВИР. Скрипт является частью более широкого проекта по обработке данных на Python, над которым я работал в течение последнего года. Проект можно найти здесь. Итак, не теряя времени, давайте перейдем к коду.

Во-первых, давайте разберем структуру данных на сайте ВИР. Мы будем парсить API ВИР, в котором хранятся различные наборы данных для Всемирного банка. API ВИР содержит данные, хранящиеся в формате xml по адресу - https://api.worldbank.org/v2/countries/all/indicators/

Любой пользователь может получить доступ к отдельным индикаторам, используя определенный код. Например, код "AG.CON.FERT.ZS" означает данные о удобрениях по странам и годам. Чтобы получить доступ к этим данным, пользователь должен указать URL - https://api.worldbank.org/v2/countries/all/indicators/AG.CON.FERT.ZS.

Итак, первый шаг - сохранить все коды из ВИР в список. Чтобы упростить это, я сохранил 300 кодов из ВИР для различных наборов данных в формате csv. Csv выглядит следующим образом:

WDICodes.csv

Чтобы сделать это еще проще, я структурировал скрипт в виде функции под названием WDIData. Давайте сначала определим функцию и импортируем необходимые библиотеки на Python. Как уже упоминалось выше, нам понадобятся пакет xml etree, numpy и pandas. Нам также понадобится пакет requests, так как это парсер.

def WDIData():
    import numpy as np
    import requests
    import pandas as pd
    import xml.etree.cElementTree as et

Теперь давайте считаем вышеупомянутый файл WDICodes в объект с именем datadict. Создадим пустой фрейм данных для хранения нашего набора данных.

datadict = pd.read_csv('input\WDI\WDICodes.csv', encoding="ISO-8859-1")
df=[]

Для каждого кода в csv мы хотим извлечь страну, код, годы и значение. Поэтому давайте создадим цикл for для кодов ВИР, где мы укажем пустые списки для каждой переменной (страна, код, год и значение). Мы также должны создать URL для запроса данных из API. Наконец, мы извлечем данные из URL с помощью функции 'fromstring' в элементе дерева.

for row in datadict['WDI Code']:
    # Укажите пустые списки для необходимых переменных
    Countryname = []
    SeriesCode = []
    Year = []
    Value = []
    # Создайте URL для каждого кода
    url = 'http://api.worldbank.org/v2/countries/all/indicators/' + str(row) + '/?format=xml&per_page=20000'
    # Получите данные из URL и сохраните в переменную
    r = requests.get(url, stream=True)
    root = et.fromstring(r.content)

Данные в каждом коде мы хотим извлечь все значения для всех лет. Это можно легко сделать с помощью циклов for, использующих функцию 'iter' внутри пакета xml tree на Python. Мы напишем 4 цикла for, один для идентификатора серии, один для названия страны, один для года и один для значения. Если вы следуете по указанному выше URL, вы заметите, что данные хранятся в определенных атрибутах.

for child in root.iter("{http://www.worldbank.org}indicator"):
    SeriesCode.append(child.attrib['id'])
for child in root.iter("{http://www.worldbank.org}country"):
    Countryname.append(child.text)
for child in root.iter("{http://www.worldbank.org}date"):
    Year.append(child.text)
for child in root.iter("{http://www.worldbank.org}value"):
    Value.append((child.text))

Теперь давайте создадим фрейм данных для каждого кода из списков. Это можно сделать с помощью функции from_dict в pandas. Мы также транспонируем набор данных. Мы сохраним данные кода во временной переменной с именем test_df.

test_df = pd.DataFrame.from_dict({'SeriesName': SeriesCode,
                                  'Country': Countryname,
                                  'Year': Year,
                                  'Value': Value}, orient='index')
test_df = test_df.transpose()

Чтобы уменьшить размер набора данных, мы удалим нулевые значения в Value, Country и SeriesName.

test_df = test_df[pd.notnull(test_df['Value'])]
test_df = test_df[pd.notnull(test_df['Country'])]
test_df = test_df[pd.notnull(test_df['Series'])]

Теперь давайте добавим данные для этого кода в первый пустой фрейм данных, который мы создали в начале. Давайте создадим таблицу из объединенного набора данных с помощью функции pivot_table в pandas. Идея использования функции pivot_table заключается в том, чтобы хранить названия серий в столбцах.

df=pd.concat(df)
data = pd.pivot_table(df, index=['Country', 'Year'], columns=['Series'], values=['Value'],
                      aggfunc=[np.sum])

Объединенный набор данных хранится в виде сводной таблицы. Давайте сохраним эту таблицу в виде записей. Наконец, давайте вернем данные и завершим функцию.

# Создайте сводную таблицу
data = pd.pivot_table(df, index=['Country', 'Year'], columns=['Series'], values=['Value'],
                      aggfunc=[np.sum])
# Преобразуйте фрейм данных в записи из сводной таблицы
data = pd.DataFrame(data.to_records())
# Завершите функцию
return (data)

Вот и все! Итоговый набор данных выглядит следующим образом. Как уже упоминалось выше, функцию WDI_Data можно найти в файле DataUpdate.py здесь. Пожалуйста, не стесняйтесь делиться любыми отзывами, которые у вас есть относительно функции. Для извлечения одной серии требуется около 5 секунд, и вы можете обновить csv-файл с до 1000 файлов, чтобы извлечь последние данные для нескольких серий.

Итоговый набор данных