Полученную диаграмму проще всего просмотреть в браузере. Откройте новую вкладку в любом браузере, а в ней откройте файл die_visual.svg (из папки, в которой был сохранен файл die_visual.py). Диаграмма должна выглядеть примерно так, как на рис. 15.11. (Мы слегка изменили изображение для печати; по умолчанию Pygal генерирует диаграммы с более темным фоном, чем на рисунке.)
Рис. 15.11. Простая гистограмма, созданная с использованием Pygal
Обратите внимание на интерактивность диаграмм, построенных с использованием Pygal: если навести указатель мыши на столбец диаграммы, вы увидите данные, связанные с этим столбцом. Данная возможность особенно полезна при нанесении нескольких наборов данных на одну диаграмму.
Бросок двух кубиков
При броске двух кубиков вы получаете большие значения с другим распределением результатов. Изменим наш код и создадим два кубика D6, моделирующих бросок пары кубиков. При броске каждой пары программа складывает два числа (по одному с каждого кубика) и сохраняет сумму в results. Сохраните копию die_visual.py под именем dice_visual.py и внесите следующие изменения:
dice_visual.py
import pygal
from die import Die
# Создание двух кубиков D6.
die_1 = Die()
die_2 = Die()
# Моделирование серии бросков с сохранением результатов в списке.
results = []
for roll_num in range(1000):
(1) . .result = die_1.roll() + die_2.roll()
results.append(result)
. .
# Анализ результатов.
frequencies = []
(2)max_result = die_1.num_sides + die_2.num_sides
(3)for value in range(2, max_result+1):
frequency = results.count(value)
frequencies.append(frequency)
. .
# Визуализация результатов.
hist = pygal.Bar()
(4)hist.title = "Results of rolling two D6 dice 1000 times."
hist.x_labels = ['2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
hist.x_title = "Result"
hist.y_title = "Frequency of Result"
hist.add('D6 + D6', frequencies)
hist.render_to_file('dice_visual.svg')
Создав два экземпляра Die, мы бросаем кубики и вычисляем сумму для каждого броска (1) . Самый большой возможный результат (12) вычисляется суммированием наибольших результатов на обоих кубиках; мы сохраняем его в max_result (2). Наименьший возможный результат (2) равен сумме наименьших результатов на обоих кубиках. В процессе анализа подсчитывается количество результатов для каждого значения от 2 до max_result (3). (Также можно было использовать диапазон range(2, 13), но он работал бы только для двух кубиков D6. При моделировании реальных ситуаций лучше писать код, который легко адаптируется для разных ситуаций. В частности, этот код позволяет смоделировать бросок пары кубиков с любым количеством граней.)
При создании диаграммы мы задаем заголовок, метки оси x и серии данных (4). (Если бы список x_labels был намного длиннее, то его было бы удобнее сгенерировать автоматически в цикле.)
После выполнения кода обновите в браузере вкладку с диаграммой; примерный вид диаграммы показан на рис. 15.12.
На диаграмме показаны примерные результаты, которые могут быть получены для пары кубиков D6. Как видите, реже всего выпадают результаты 2 и 12, а чаще всего 7, потому что эта комбинация может быть выброшена шестью способами: 1+6, 2+5, 3+4, 4+3, 5+2 и 6+1.
Рис. 15.12. Смоделированные результаты 1000 бросков двух шестигранных кубиков
Броски кубиков с разным числом граней
Создадим кубики с 6 и 10 гранями и посмотрим, что произойдет, если бросить их 50 000 раз:
different_dice.py
from die import Die
import pygal
# Создание кубиков D6 и D10.
die_1 = Die()
(1) die_2 = Die(10)
# Моделирование серии бросков с сохранением результатов в списке.
results = []
for roll_num in range(50000):
result = die_1.roll() + die_2.roll()
results.append(result)
. .
# Analyze the results.
...
. .
# Визуализация результатов.
hist = pygal.Bar()
(2)hist.title = "Results of rolling a D6 and a D10 50,000 times."
hist.x_labels = ['2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12',
. .'13', '14', '15', '16']
hist.x_title = "Result"
hist.y_title = "Frequency of Result"
hist.add('D6 + D10', frequencies)
hist.render_to_file('dice_visual.svg')
Чтобы создать модель кубика D10, мы передаем аргумент 10 при создании второго экземпляра Die1 и изменяем первый цикл для моделирования 50 000 бросков вместо 1000. Наименьший возможный результат, как и прежде, равен 2, зато наибольший увеличился до 16; мы соответственно изменяем заголовок, метки оси x и метки серии данных (2).
На рис. 15.13 показана полученная диаграмма. Вместо одного наиболее вероятного результата их стало целых пять. Это объясняется тем, что наименьшее (1+1) и наибольшее (6+10) значения по-прежнему могут быть получены только одним способом, но кубик D6 ограничивает количество способов генерирования средних чисел: суммы 7, 8, 9, 10 и 11 можно выбросить шестью способами. Следовательно, именно эти результаты являются наиболее частыми, и все эти числа выпадают с равной вероятностью.
Рис. 15.13. Результаты 50 000 бросков шести- и десятигранного кубиков