Парсинг базы данных Всемирных индикаторов развития (ВИР) с использованием Python
Table Of Content
- В этой статье представлено пошаговое руководство по созданию функции на Python, которая использует пакет xmltree для парсинга и обработки последних данных из базы данных ВИР для нескольких серий одновременно.
- Создайте сводную таблицу
- Преобразуйте фрейм данных в записи из сводной таблицы
- Завершите функцию
В этой статье представлено пошаговое руководство по созданию функции на 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 выглядит следующим образом:
Чтобы сделать это еще проще, я структурировал скрипт в виде функции под названием 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 файлов, чтобы извлечь последние данные для нескольких серий.