Скопируйте файл population_data.json, содержащий данные о численности населения большинства стран мира с 1960 по 2010 год, в каталог с программами этой главы. Информация взята из многочисленных наборов данных, бесплатно публикуемых фондом Open Knowledge Foundation (http://data.okfn.org/).
Взглянем на файл population_data.json и попробуем понять, как взяться за обработку данных файла:
population_data.json
[
{
. ."Country Name": "Arab World",
. ."Country Code": "ARB",
. ."Year": "1960",
. ."Value": "96388069"
},
{
. ."Country Name": "Arab World",
. ."Country Code": "ARB",
. ."Year": "1961",
. ."Value": "98882541.4"
},
...
]
Фактически перед нами один длинный список Python. Каждый элемент списка представляет собой словарь с четырьмя ключами: название страны (Country Name), код страны (Country Code), год (Year) и значение (Value), представляющее численность населения. В нашей программе будут использоваться названия стран и численность населения только за 2010 год, поэтому для начала напишем программу, которая выводит только эту информацию:
world_population.py
import json
# Список заполняется данными.
filename = 'population_data.json'
with open(filename) as f:
(1) . .pop_data = json.load(f)
# Вывод населения каждой страны за 2010 год.
(2)for pop_dict in pop_data:
(3) . .if pop_dict['Year'] == '2010':
(4) . . . .country_name = pop_dict['Country Name']
. . . .population = pop_dict['Value']
. . . .print(country_name + ": " + population)
Сначала программа импортирует модуль json, чтобы иметь возможность загружать данные из файла. Загруженные данные сохраняются в списке pop_data (1) . Функция json.load() преобразует данные в формат, с которым может работать Python: в данном случае это список. В точке (2) создается цикл, перебирающий все элементы pop_data. Каждый элемент представляет собой словарь с четырьмя парами «ключ—значение», который сохраняется в переменной pop_dict.
В точке (3) ключ 'Year' каждого словаря проверяется на значение 2010. (Так как все значения population_data.json заключены в кавычки, выполняется сравнение строк.) Если словарь относится к 2010 году, то значение, связанное с ключом 'Country Name', сохраняется в переменной country_name, а значение, связанное с ключом 'Value', сохраняется в переменной population (4). Затем программа выводит название каждой страны и ее население.
Программа выводит последовательность названий стран и численности их населения:
Arab World: 357868000
Caribbean small states: 6880000
East Asia & Pacific (all income levels): 2201536674
...
Zimbabwe: 12571000
Не все данные включают точные названия стран, но это неплохое начало для дальнейшей работы. Теперь данные необходимо преобразовать в формат, с которым может работать Pygal.
Все ключи и значения в population_data.json хранятся в строковом формате. Чтобы работать с данными численности населения, необходимо преобразовать строковые значения в числа. Для этого в программе используется функция int():
world_population.py
...
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country_name = pop_dict['Country Name']
(1) . . . .population = int(pop_dict['Value'])
(2) . . . .print(country_name + ": " + str(population))
После преобразования (1) все данные численности населения хранятся в числовом формате. При выводе численность населения должна быть преобразована в строку (2). Впрочем, для некоторых значений это изменение приводит к ошибке:
Arab World: 357868000
Caribbean small states: 6880000
East Asia & Pacific (all income levels): 2201536674
...
Traceback (most recent call last):
File "print_populations.py", line 12, in
. .population = int(pop_dict['Value'])
(1) ValueError: invalid literal for int() with base 10: '1127437398.85751'
Необработанные данные часто форматируются непоследовательно, поэтому ошибки в них встречаются достаточно часто. В данном случае ошибка происходит из-за того, что Python не может преобразовать строку с дробным значением '1127437398.85751' в целое число (1) . (Вероятно, дробное значение было получено в результате интерполяции в те годы, в которые перепись населения не производилась.) Чтобы решить эту проблему, мы сначала преобразуем строку в вещественное число, а затем преобразуем вещественное число в целое:
world_population.py
...
for pop_dict in pop_data:
if pop_dict['Year'] == '2010':
country = pop_dict['Country Name']
. . . .population = int(float(pop_dict['Value']))
print(country + ": " + str(population))
Функция float() преобразует строку в целое число, а функция int() отсекает дробную часть и возвращает целое число. Теперь можно вывести полный набор данных численности населения за 2010 год без ошибок:
Arab World: 357868000
Caribbean small states: 6880000
East Asia & Pacific (all income levels): 2201536674
...
Zimbabwe: 12571000