Диаграммы - отличный способ быстро визуализировать и понять огромное количество данных. Существует множество различных типов диаграмм: столбчатая диаграмма, линейная диаграмма, круговая диаграмма, и так далее. Модуль openpyxl
поддерживает многие из них.
Здесь будут разбираться приемы создания наиболее часто используемых диаграмм - это столбчатая и линейная диаграммы. Так как теория лежащая в основе создания диаграмм одинакова, создание остальных типов диаграмм не составит труда.
Примечание: В зависимости от того, что используется для просмотра документа XLSX - Microsoft Excel или альтернатива с открытым исходным кодом (LibreOffice Calc или OpenOffice Calc), диаграмма может выглядеть немного иначе. В частности, LibreOffice Calc неправильно отображает подписи осей, заголовок диаграммы вообще не выводится. Кстати китайский WPS Office Calc отображает все корректно.
Диаграммы состоят, по крайней мере, из одного или нескольких рядов данных. Сами ряды данных состоят из ссылок на диапазоны ячеек.
from openpyxl import Workbook from openpyxl.chart import BarChart, Reference wb = Workbook() ws = wb.active # данные для диаграммы data = [ ["Product", "Online", "Store"], [1, 30, 45], [2, 40, 30], [3, 40, 25], [4, 50, 30], [5, 30, 25], [6, 25, 35], [7, 20, 40], ] for row in data: ws.append(row) # выбираем диапазоны значений для диаграммы values = Reference(worksheet=ws, min_row=1, max_row=8, min_col=2, max_col=3) # создаем объект столбчатой диаграммы chart = BarChart() # добавляем в диаграмму выбранный диапазон значений chart.add_data(values, titles_from_data=True) # привязываем диаграмму к ячейке `E15` ws.add_chart(chart, "A11") # определяем размеры диаграммы в сантиметрах chart.width = 20 chart.height = 5 # сохраняем и смотрим что получилось wb.save("sample-chart.xlsx")
По умолчанию верхний левый угол диаграммы привязан к ячейке 'A11'
и имеет размер 15 x 7,5 см. Размеры диаграммы можно изменить, задав нижеуказанные свойства:
chart.width
- ширина диаграммы, по умолчанию 15 сантиметров. chart.heigh
- высота диаграммы, по умолчанию 7,5 сантиметров.Внимание. Фактический размер будет зависеть от операционной системы и устройства.
На столбчатых гистограммах, значения отображаются либо в виде горизонтальных полос, либо в виде вертикальных столбцов.
Следующие настройки влияют на вид столбчатых гистограмм:
.type = "col"
(вертикальные столбцы) или .type = "bar"
(горизонтальные полосы)..overlap
необходимо установить значение 100.x
и y
меняются местами..grouping
может принимать одно из значений: 'percentStacked'
, 'stacked'
, 'standard'
(по умолчанию).Смотрим пример четырех гистограмм, который иллюстрирует различные возможности и настройки (с подробным описанием кода):
from copy import deepcopy from openpyxl import Workbook from openpyxl.chart import BarChart, Reference wb = Workbook() ws = wb.active # данные для построения диаграмм rows = [ ('Number', 'Batch 1', 'Batch 2'), (2, 10, 30), (3, 40, 60), (4, 50, 70), (5, 20, 10), (6, 10, 40), (7, 50, 30), ] for row in rows: ws.append(row) # ДИАГРАММА №1 # создаем объект диаграммы chart1 = BarChart() # установим тип - `вертикальные столбцы` chart1.type = "col" # установим стиль диаграммы (цветовая схема) chart1.style = 10 # заголовок диаграммы chart1.title = "Столбчатая диаграмма" # подпись оси `y` chart1.y_axis.title = 'Длина выборки' # показывать данные на оси (для LibreOffice Calc) chart1.y_axis.delete = False # подпись оси `x` chart1.x_axis.title = 'Номер теста' chart1.x_axis.delete = False # выберем 2 столбца с данными для оси `y` data = Reference(ws, min_col=2, max_col=3, min_row=1, max_row=7) # теперь выберем категорию для оси `x` categor = Reference(ws, min_col=1, min_row=2, max_row=7) # добавляем данные в объект диаграммы chart1.add_data(data, titles_from_data=True) # установим метки на объект диаграммы chart1.set_categories(categor) # добавим диаграмму на лист, в ячейку "A10" ws.add_chart(chart1, "A10") # ДИАГРАММА №2 # что бы показать типы столбчатых диаграмм, скопируем # первую диаграмму и будем менять настройки chart2 = deepcopy(chart1) # изменяем стиль chart2.style = 11 # установим тип - `горизонтальные полосы` chart2.type = "bar" chart2.title = "Горизонтальные полосы" ws.add_chart(chart2, "A25") # ДИАГРАММА №3 chart3 = deepcopy(chart1) chart3.type = "col" chart3.style = 12 # зададим группировку chart3.grouping = "stacked" # для диаграммы с группировкой, # необходимо установить перекрытие chart3.overlap = 100 chart3.title = 'Сложенная диаграмма' ws.add_chart(chart3, "A40") # ДИАГРАММА №4 chart4 = deepcopy(chart1) chart4.type = "bar" chart4.style = 13 chart4.grouping = "percentStacked" chart4.overlap = 100 # отключим линии сетки chart4.y_axis.majorGridlines = None # уберем легенду chart4.legend = None chart4.title = 'Диаграмма с процентным накоплением' ws.add_chart(chart4, "A55") # сохраняем и смотрим что получилось wb.save("bar.xlsx")
При помощи модуля openpyxl
также можно создавать трехмерные гистограммы. Смотрим пример простой трехмерной гистограммы:
from openpyxl import Workbook from openpyxl.chart import Reference, BarChart3D wb = Workbook() ws = wb.active rows = [ (None, 2013, 2014), ("Apples", 5, 4), ("Oranges", 6, 2), ("Pears", 8, 3) ] for row in rows: ws.append(row) data = Reference(ws, min_col=2, min_row=1, max_col=3, max_row=4) titles = Reference(ws, min_col=1, min_row=2, max_row=4) chart = BarChart3D() chart.title = "3D Bar Chart" chart.add_data(data=data, titles_from_data=True) chart.set_categories(titles) ws.add_chart(chart, "E5") wb.save("bar3d.xlsx")
Линейные диаграммы позволяют отображать данные относительно фиксированной оси. Они похожи на точечные диаграммы, главное отличие состоит в том, что в линейных диаграммах каждый ряд данных отображается на основе одних и тех же значений. В качестве вспомогательных осей можно использовать различные типы осей.
Как и столбчатые гистограммы, линейные диаграммы бывают трех видов: 'standard'
(стандартные), 'stacked'
(с накоплением) и 'percentStacked'
(с процентным накоплением).
Смотрим пример линейных диаграмм, который иллюстрирует различные возможности и настройки (с подробным описанием кода):
from openpyxl import Workbook from openpyxl.chart import LineChart, Reference from openpyxl.chart.axis import DateAxis from datetime import date from copy import deepcopy wb = Workbook() ws = wb.active # данные для построения диаграммы rows = [ ['Date', 'Batch 1', 'Batch 2', 'Batch 3'], [date(2015,9, 1), 40, 30, 25], [date(2015,9, 2), 40, 25, 30], [date(2015,9, 3), 50, 30, 45], [date(2015,9, 4), 30, 25, 40], [date(2015,9, 5), 25, 35, 30], [date(2015,9, 6), 20, 40, 35], ] for row in rows: ws.append(row) # ДИАГРАММА №1 # создаем объект диаграммы chart1 = LineChart() # заголовок диаграммы chart1.title = "Линейная диаграмма" # установим цветовую схему диаграммы chart1.style = 13 # подпись оси `y` chart1.y_axis.title = 'Размер' # показывать данные на оси (для LibreOffice Calc) chart1.y_axis.delete = False # подпись оси `x` chart1.x_axis.title = 'Номер теста' chart1.x_axis.delete = False # выберем 4 столбца с данными для оси `y` # в итоге получим 4 графика data = Reference(ws, min_col=2, max_col=4, min_row=1, max_row=7) # добавляем данные в объект диаграммы chart1.add_data(data, titles_from_data=True) # ТЕПЕРЬ ЗАДАДИМ СТИЛЬ ЛИНИЙ # ЛИНИЯ С ДАННЫМИ ИЗ 1 СТОЛБЦА ДАННЫХ line1 = chart1.series[0] # символ маркера для текущего значения line1.marker.symbol = "x" # цвет заливки маркера line1.marker.graphicalProperties.solidFill = "FF0000" line1.marker.graphicalProperties.line.solidFill = "FF0000" # не заливаем линию между маркерами (прозрачная) line1.graphicalProperties.line.noFill = True # ЛИНИЯ С ДАННЫМИ ИЗ 2 СТОЛБЦА ДАННЫХ line2 = chart1.series[1] # цвет заливки линии графика line2.graphicalProperties.line.solidFill = "00AAAA" # делаем линию пунктирной line2.graphicalProperties.line.dashStyle = "sysDot" # ширина указывается в EMU line2.graphicalProperties.line.width = 100050 # ЛИНИЯ С ДАННЫМИ ИЗ 3 СТОЛБЦА ДАННЫХ line3 = chart1.series[2] # символ маркера для текущего значения line3.marker.symbol = "triangle" # покрасим маркер в другой цвет line1.marker.graphicalProperties.solidFill = "FF0000" line3.marker.graphicalProperties.line.solidFill = "0000FF" # делаем линию гладкой line3.smooth = True # добавим диаграмму на лист, в ячейку "A10" ws.add_chart(chart1, "A10") # ДИАГРАММА №2 # скопируем первую диаграмму stacked = deepcopy(chart1) # диаграмма с накоплением stacked.grouping = "stacked" stacked.title = "Графики с накоплением" ws.add_chart(stacked, "A27") # ДИАГРАММА №3 percent_stacked = deepcopy(chart1) # диаграмма с процентным накоплением percent_stacked.grouping = "percentStacked" percent_stacked.title = "Графики с процентным накоплением" ws.add_chart(percent_stacked, "A44") # ДИАГРАММА №4 с датами по оси `x`, все линии # графиков будут иметь стиль по умолчанию # создаем объект диаграммы chart2 = LineChart() chart2.title = "Графики с осью дат" # установим другую цветовую схему chart2.style = 12 # подпись оси `y` chart2.y_axis.title = "Размер" chart2.y_axis.delete = False # поперечная ось chart2.y_axis.crossAx = 500 # подпись оси `x` chart2.x_axis.title = "Дата" chart2.x_axis.delete = False chart2.x_axis = DateAxis(crossAx=100) # формат отображения дат на оси `x` chart2.x_axis.number_format = 'd-mmm' # задаем временную единицу даты chart2.x_axis.majorTimeUnit = "days" # добавляем выборку данных из первой диаграммы chart2.add_data(data, titles_from_data=True) # делаем выборку данных для оси `x` dates = Reference(ws, min_col=1, min_row=2, max_row=7) chart2.set_categories(dates) ws.add_chart(chart2, "A61") # сохраняем и смотрим что получилось wb.save("line.xlsx")
Примечание:
dashStyle
может принимать одно из значений: ‘dot’
, ‘lgDashDot’
, ‘lgDashDotDot’
, ‘sysDash’
, ‘lgDash’
, ‘sysDot’
, ‘solid’
(по умолчанию), ‘dashDot’
, ‘sysDashDotDot’
, ‘dash’
, ‘sysDashDot’
marker.symbol
может принимать одно из значений: ‘dot’
, ‘plus’
, ‘triangle’
, ‘x’
, ‘star’
, ‘diamond’
, ‘square’
, ‘circle’
, ‘dash’
, ‘auto’
(по умолчанию).В трехмерных линейных диаграммах проекция третьей оси совпадает с названием столбцов выбранных данных, в общем с легендой.
from datetime import date from openpyxl import Workbook from openpyxl.chart import LineChart3D, Reference from openpyxl.chart.axis import DateAxis wb = Workbook() ws = wb.active rows = [ ['Date', 'Batch 1', 'Batch 2', 'Batch 3'], [date(2015,9, 1), 40, 30, 25], [date(2015,9, 2), 40, 25, 30], [date(2015,9, 3), 50, 30, 45], [date(2015,9, 4), 30, 25, 40], [date(2015,9, 5), 25, 35, 30], [date(2015,9, 6), 20, 40, 35], ] for row in rows: ws.append(row) # создаем объект диаграммы chart = LineChart3D() # устанавливаем атрибуты chart.title = "3D Линейный график" # легенда не нужна, т.к. 3-я ось совпадает # с названиями столбцов выборки chart.legend = None chart.style = 15 chart.y_axis.title = 'Размер' chart.x_axis.title = 'Номер теста' # делаем выборку и добавляем ее в объект диаграммы data = Reference(ws, min_col=2, min_row=1, max_col=4, max_row=7) chart.add_data(data, titles_from_data=True) # добавляем диаграмму на лист в ячейку "A10" ws.add_chart(chart, "A10") # сохраняем и смотрим что получилось wb.save("line3D.xlsx")
Диаграммы можно добавлять в специальные рабочие листы, называемые таблицами диаграмм, которые содержат только диаграммы.
Все данные для диаграммы должны быть на другом листе электронной таблицы.
from openpyxl import Workbook from openpyxl.chart import PieChart, Reference, Series wb = Workbook() ws = wb.active # создаем таблицу диаграммы chartsheet = wb.create_chartsheet("Круговая диаграмма") rows = [ ["Bob", 3], ["Harry", 2], ["James", 4], ] for row in rows: ws.append(row) # создаем rheujde. lbfuhfvve chart = PieChart() # выбираем данные labels = Reference(ws, min_col=1, min_row=1, max_row=3) data = Reference(ws, min_col=2, min_row=1, max_row=3) # добавляем данные chart.add_data(data, titles_from_data=False) chart.set_categories(labels) chart.title = "Круговая диаграмма" # размеры диаграммы chart.width = 15 chart.height = 15 # добавляем на лист диаграмм chartsheet.add_chart(chart) wb.save("create_chartsheet.xlsx")
Минимальные и максимальные значения осей можно установить вручную для отображения определенных регионов на диаграмме.
from openpyxl import Workbook from openpyxl.chart import ScatterChart, Reference, Series wb = Workbook() ws = wb.active # данные диаграммы ws.append(['X', '1/X']) for x in range(-10, 11): if x: ws.append([x, 1.0 / x]) # ДИАГРАММА 1 chart1 = ScatterChart() chart1.title = "Полные Оси" chart1.x_axis.title = 'x' chart1.x_axis.delete = False chart1.y_axis.title = '1/x' chart1.y_axis.delete = False chart1.legend = None # ДИАГРАММА 2 chart2 = ScatterChart() chart2.title = "Clipped Axes" chart2.x_axis.title = 'x' chart2.x_axis.delete = False chart2.y_axis.title = '1/x' chart2.y_axis.delete = False chart2.legend = None # устанавливаем минимумы chart2.x_axis.scaling.min = 0 chart2.y_axis.scaling.min = 0 # устанавливаем максимумы chart2.x_axis.scaling.max = 11 chart2.y_axis.scaling.max = 1.5 # делаем выборку x = Reference(ws, min_col=1, min_row=2, max_row=22) y = Reference(ws, min_col=2, min_row=2, max_row=22) # собираем серию series = Series(y, xvalues=x) # добавляем в объекты диаграмм chart1.append(series) chart2.append(series) # добавляем диаграммы на лист Excel ws.add_chart(chart1, "d1") ws.add_chart(chart2, "d17") wb.save("minmax.xlsx")
Примечание. В некоторых случаях, таких как в примере, установка пределов оси фактически эквивалентна отображению поддиапазона данных. Для больших наборов данных визуализация точечных диаграмм (и, возможно, других) будет намного быстрее при использовании подмножеств данных, а не ограничений по осям как в Excel, так и в OpenOffice Calc/LibreOffice Calc.