[{"data":1,"prerenderedAt":1520},["ShallowReactive",2],{"doc:\u002Fpyqgis-cartography-visualization\u002Fdiagrams-and-charts-on-maps\u002Fadd-histogram-bar-diagrams-pyqgis":3},{"id":4,"title":5,"body":6,"description":1509,"extension":1510,"meta":1511,"navigation":237,"path":1516,"seo":1517,"stem":1518,"__hash__":1519},"docs\u002Fpyqgis-cartography-visualization\u002Fdiagrams-and-charts-on-maps\u002Fadd-histogram-bar-diagrams-pyqgis\u002Findex.md","Add Histogram Bar Diagrams in PyQGIS",{"type":7,"value":8,"toc":1494},"minimark",[9,13,17,26,149,154,164,168,171,518,529,533,536,709,714,718,721,811,903,908,912,915,959,969,973,976,1057,1062,1066,1073,1150,1338,1343,1347,1360,1364,1378,1382,1419,1423,1429,1433,1439,1445,1451,1457,1461,1490],[10,11,5],"h1",{"id":12},"add-histogram-bar-diagrams-in-pyqgis",[14,15,16],"p",{},"Bars are the chart people read most accurately. Comparing the lengths of two bars is far easier than comparing two pie slices, which is why a small bar chart on each feature often communicates better than a pie: monthly rainfall at each station, the number of jobs in each sector per district, emissions by source in each city. QGIS calls this diagram type a histogram, though it draws one bar per category rather than a frequency distribution.",[14,18,19,20,25],{},"This recipe belongs to ",[21,22,24],"a",{"href":23},"\u002Fpyqgis-cartography-visualization\u002Fdiagrams-and-charts-on-maps\u002F","Diagrams & Charts on Maps",". It builds a histogram diagram renderer, fixes a common scale so bars are comparable across features, controls orientation, width and spacing, adds axes, and keeps the result readable when printed.",[14,27,28],{},[29,30,35,39,43,50,59,69,76,81,87,90,93,96,102,106,112,115,118,121,124,129,133,138,141,144],"svg",{"viewBox":31,"role":32,"ariaLabel":33,"xmlns":34},"0 0 760 258","img","Two bar diagrams scaled independently look equally tall, while a shared scale makes the smaller district's bars visibly shorter","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[36,37,38],"title",{},"Why one scale for all features",[40,41,42],"desc",{},"Two districts with bar diagrams. With each diagram scaled to its own maximum, a small district's bars look as tall as a large district's, hiding the difference in magnitude. With a shared scale, the small district's bars are visibly shorter, so bars can be compared across the map as well as within each diagram.",[44,45],"rect",{"x":46,"y":46,"width":47,"height":48,"fill":49},"0","760","258","#f6f3ea",[51,52,58],"text",{"x":53,"y":54,"style":55,"fill":56,"textAnchor":57},"380","28","text-anchor:middle;font-size:14px;font-family:sans-serif;font-weight:bold","#17211d","middle","Bars only compare across features on one scale",[44,60],{"x":61,"y":62,"width":63,"height":64,"rx":65,"fill":66,"stroke":67,"style":68},"24","52","340","190","8","#fffdf7","#59645f","stroke-width:1.5",[44,70],{"x":71,"y":72,"width":73,"height":74,"rx":46,"fill":75,"stroke":75,"style":68},"70","110","18","100","#0f766e",[44,77],{"x":78,"y":79,"width":73,"height":71,"rx":46,"fill":80,"stroke":80,"style":68},"92","140","#2563eb",[44,82],{"x":83,"y":84,"width":73,"height":85,"rx":46,"fill":86,"stroke":86,"style":68},"114","160","50","#b45309",[44,88],{"x":89,"y":72,"width":73,"height":74,"rx":46,"fill":75,"stroke":75,"style":68},"230",[44,91],{"x":92,"y":79,"width":73,"height":71,"rx":46,"fill":80,"stroke":80,"style":68},"252",[44,94],{"x":95,"y":84,"width":73,"height":85,"rx":46,"fill":86,"stroke":86,"style":68},"274",[51,97,101],{"x":98,"y":89,"style":99,"fill":100,"textAnchor":57},"101","text-anchor:middle;font-size:10.5px;font-family:sans-serif","#2f3b35","large",[51,103,105],{"x":104,"y":89,"style":99,"fill":100,"textAnchor":57},"261","small",[51,107,111],{"x":108,"y":109,"style":99,"fill":110,"textAnchor":57},"194","82","#b91c1c","own maximum each: misleading",[44,113],{"x":114,"y":62,"width":63,"height":64,"rx":65,"fill":66,"stroke":67,"style":68},"396",[44,116],{"x":117,"y":72,"width":73,"height":74,"rx":46,"fill":75,"stroke":75,"style":68},"442",[44,119],{"x":120,"y":79,"width":73,"height":71,"rx":46,"fill":80,"stroke":80,"style":68},"464",[44,122],{"x":123,"y":84,"width":73,"height":85,"rx":46,"fill":86,"stroke":86,"style":68},"486",[44,125],{"x":126,"y":127,"width":73,"height":128,"rx":46,"fill":75,"stroke":75,"style":68},"602","185","25",[44,130],{"x":131,"y":132,"width":73,"height":73,"rx":46,"fill":80,"stroke":80,"style":68},"624","192",[44,134],{"x":135,"y":136,"width":73,"height":137,"rx":46,"fill":86,"stroke":86,"style":68},"646","198","12",[51,139,101],{"x":140,"y":89,"style":99,"fill":100,"textAnchor":57},"473",[51,142,105],{"x":143,"y":89,"style":99,"fill":100,"textAnchor":57},"633",[51,145,148],{"x":146,"y":109,"style":99,"fill":147,"textAnchor":57},"566","#166534","shared scale: honest",[150,151,153],"h2",{"id":152},"prerequisites","Prerequisites",[155,156,157,161],"ul",{},[158,159,160],"li",{},"QGIS 3.34 LTR or newer, or the QGIS 4 series.",[158,162,163],{},"A layer with numeric fields in the same unit — counts, amounts or rates — that should be compared both within and across features.",[150,165,167],{"id":166},"build-a-histogram-diagram","Build a histogram diagram",[14,169,170],{},"The structure is the same as for pies: a diagram type, settings with categories, a renderer and layer settings. For bars, the linearly interpolated renderer is the natural choice, because it is what maps values to bar lengths on a shared scale.",[172,173,178],"pre",{"className":174,"code":175,"language":176,"meta":177,"style":177},"language-python shiki shiki-themes github-dark","from qgis.core import (QgsProject, QgsHistogramDiagram, QgsDiagramSettings,\n                       QgsLinearlyInterpolatedDiagramRenderer, QgsDiagramLayerSettings)\nfrom qgis.PyQt.QtGui import QColor\nfrom qgis.PyQt.QtCore import QSizeF\n\nregions = QgsProject.instance().mapLayersByName(\"regions\")[0]\nfields = [\"jobs_industry\", \"jobs_services\", \"jobs_public\", \"jobs_agri\"]\n\nsettings = QgsDiagramSettings()\nsettings.categoryAttributes = [f'\"{f}\"' for f in fields]\nsettings.categoryColors = [QColor(c) for c in (\"#b45309\", \"#2563eb\", \"#0f766e\", \"#15803d\")]\nsettings.categoryLabels = [\"industry\", \"services\", \"public\", \"agriculture\"]\nsettings.barWidth = 2.0                       # mm\nsettings.penColor = QColor(\"#2f3b35\")\nsettings.penWidth = 0.1\nsettings.enabled = True\n\nrenderer = QgsLinearlyInterpolatedDiagramRenderer()\nrenderer.setDiagram(QgsHistogramDiagram())\nrenderer.setDiagramSettings(settings)\nregions.setDiagramRenderer(renderer)\nregions.setDiagramLayerSettings(QgsDiagramLayerSettings())\n","python","",[179,180,181,200,206,219,232,239,264,296,301,312,351,394,424,439,456,467,478,483,494,500,506,512],"code",{"__ignoreMap":177},[182,183,186,190,194,197],"span",{"class":184,"line":185},"line",1,[182,187,189],{"class":188},"snl16","from",[182,191,193],{"class":192},"s95oV"," qgis.core ",[182,195,196],{"class":188},"import",[182,198,199],{"class":192}," (QgsProject, QgsHistogramDiagram, QgsDiagramSettings,\n",[182,201,203],{"class":184,"line":202},2,[182,204,205],{"class":192},"                       QgsLinearlyInterpolatedDiagramRenderer, QgsDiagramLayerSettings)\n",[182,207,209,211,214,216],{"class":184,"line":208},3,[182,210,189],{"class":188},[182,212,213],{"class":192}," qgis.PyQt.QtGui ",[182,215,196],{"class":188},[182,217,218],{"class":192}," QColor\n",[182,220,222,224,227,229],{"class":184,"line":221},4,[182,223,189],{"class":188},[182,225,226],{"class":192}," qgis.PyQt.QtCore ",[182,228,196],{"class":188},[182,230,231],{"class":192}," QSizeF\n",[182,233,235],{"class":184,"line":234},5,[182,236,238],{"emptyLinePlaceholder":237},true,"\n",[182,240,242,245,248,251,255,258,261],{"class":184,"line":241},6,[182,243,244],{"class":192},"regions ",[182,246,247],{"class":188},"=",[182,249,250],{"class":192}," QgsProject.instance().mapLayersByName(",[182,252,254],{"class":253},"sU2Wk","\"regions\"",[182,256,257],{"class":192},")[",[182,259,46],{"class":260},"sDLfK",[182,262,263],{"class":192},"]\n",[182,265,267,270,272,275,278,281,284,286,289,291,294],{"class":184,"line":266},7,[182,268,269],{"class":192},"fields ",[182,271,247],{"class":188},[182,273,274],{"class":192}," [",[182,276,277],{"class":253},"\"jobs_industry\"",[182,279,280],{"class":192},", ",[182,282,283],{"class":253},"\"jobs_services\"",[182,285,280],{"class":192},[182,287,288],{"class":253},"\"jobs_public\"",[182,290,280],{"class":192},[182,292,293],{"class":253},"\"jobs_agri\"",[182,295,263],{"class":192},[182,297,299],{"class":184,"line":298},8,[182,300,238],{"emptyLinePlaceholder":237},[182,302,304,307,309],{"class":184,"line":303},9,[182,305,306],{"class":192},"settings ",[182,308,247],{"class":188},[182,310,311],{"class":192}," QgsDiagramSettings()\n",[182,313,315,318,320,322,325,328,331,333,336,339,342,345,348],{"class":184,"line":314},10,[182,316,317],{"class":192},"settings.categoryAttributes ",[182,319,247],{"class":188},[182,321,274],{"class":192},[182,323,324],{"class":188},"f",[182,326,327],{"class":253},"'\"",[182,329,330],{"class":260},"{",[182,332,324],{"class":192},[182,334,335],{"class":260},"}",[182,337,338],{"class":253},"\"'",[182,340,341],{"class":188}," for",[182,343,344],{"class":192}," f ",[182,346,347],{"class":188},"in",[182,349,350],{"class":192}," fields]\n",[182,352,354,357,359,362,365,368,370,373,376,378,381,383,386,388,391],{"class":184,"line":353},11,[182,355,356],{"class":192},"settings.categoryColors ",[182,358,247],{"class":188},[182,360,361],{"class":192}," [QColor(c) ",[182,363,364],{"class":188},"for",[182,366,367],{"class":192}," c ",[182,369,347],{"class":188},[182,371,372],{"class":192}," (",[182,374,375],{"class":253},"\"#b45309\"",[182,377,280],{"class":192},[182,379,380],{"class":253},"\"#2563eb\"",[182,382,280],{"class":192},[182,384,385],{"class":253},"\"#0f766e\"",[182,387,280],{"class":192},[182,389,390],{"class":253},"\"#15803d\"",[182,392,393],{"class":192},")]\n",[182,395,397,400,402,404,407,409,412,414,417,419,422],{"class":184,"line":396},12,[182,398,399],{"class":192},"settings.categoryLabels ",[182,401,247],{"class":188},[182,403,274],{"class":192},[182,405,406],{"class":253},"\"industry\"",[182,408,280],{"class":192},[182,410,411],{"class":253},"\"services\"",[182,413,280],{"class":192},[182,415,416],{"class":253},"\"public\"",[182,418,280],{"class":192},[182,420,421],{"class":253},"\"agriculture\"",[182,423,263],{"class":192},[182,425,427,430,432,435],{"class":184,"line":426},13,[182,428,429],{"class":192},"settings.barWidth ",[182,431,247],{"class":188},[182,433,434],{"class":260}," 2.0",[182,436,438],{"class":437},"sjoCn","                       # mm\n",[182,440,442,445,447,450,453],{"class":184,"line":441},14,[182,443,444],{"class":192},"settings.penColor ",[182,446,247],{"class":188},[182,448,449],{"class":192}," QColor(",[182,451,452],{"class":253},"\"#2f3b35\"",[182,454,455],{"class":192},")\n",[182,457,459,462,464],{"class":184,"line":458},15,[182,460,461],{"class":192},"settings.penWidth ",[182,463,247],{"class":188},[182,465,466],{"class":260}," 0.1\n",[182,468,470,473,475],{"class":184,"line":469},16,[182,471,472],{"class":192},"settings.enabled ",[182,474,247],{"class":188},[182,476,477],{"class":260}," True\n",[182,479,481],{"class":184,"line":480},17,[182,482,238],{"emptyLinePlaceholder":237},[182,484,486,489,491],{"class":184,"line":485},18,[182,487,488],{"class":192},"renderer ",[182,490,247],{"class":188},[182,492,493],{"class":192}," QgsLinearlyInterpolatedDiagramRenderer()\n",[182,495,497],{"class":184,"line":496},19,[182,498,499],{"class":192},"renderer.setDiagram(QgsHistogramDiagram())\n",[182,501,503],{"class":184,"line":502},20,[182,504,505],{"class":192},"renderer.setDiagramSettings(settings)\n",[182,507,509],{"class":184,"line":508},21,[182,510,511],{"class":192},"regions.setDiagramRenderer(renderer)\n",[182,513,515],{"class":184,"line":514},22,[182,516,517],{"class":192},"regions.setDiagramLayerSettings(QgsDiagramLayerSettings())\n",[14,519,520,524,525,528],{},[521,522,523],"strong",{},"Breakdown:"," Categories are expressions, so each field name is wrapped in double quotes. ",[179,526,527],{},"barWidth"," is the width of each bar in millimetres; the diagram's total width follows from the number of bars. A thin dark outline keeps light-coloured bars visible against a pale map. Nothing is scaled yet — that is the next step, and the most important one.",[150,530,532],{"id":531},"set-a-shared-scale","Set a shared scale",[14,534,535],{},"Bar length is set by mapping a value range to a length range. The upper value should be the largest single category value across all features, so the tallest bar on the map has the maximum length and everything else is proportional to it.",[172,537,539],{"className":174,"code":538,"language":176,"meta":177,"style":177},"max_value = max(max(f[name] or 0 for name in fields) for f in regions.getFeatures())\n\nrenderer.setClassificationAttributeExpression(\n    \"max(\" + \", \".join(f'coalesce(\"{f}\", 0)' for f in fields) + \")\")\nrenderer.setLowerValue(0)\nrenderer.setUpperValue(max_value)\nrenderer.setLowerSize(QSizeF(0, 0))\nrenderer.setUpperSize(QSizeF(0, 18))           # tallest bar: 18 mm\nrenderer.setDiagramSettings(settings)\nregions.setDiagramRenderer(renderer)\nregions.triggerRepaint()\nprint(\"tallest bar represents\", max_value)\n",[179,540,541,585,589,594,638,647,652,666,683,687,691,696],{"__ignoreMap":177},[182,542,543,546,548,551,554,557,560,563,566,568,571,573,576,578,580,582],{"class":184,"line":185},[182,544,545],{"class":192},"max_value ",[182,547,247],{"class":188},[182,549,550],{"class":260}," max",[182,552,553],{"class":192},"(",[182,555,556],{"class":260},"max",[182,558,559],{"class":192},"(f[name] ",[182,561,562],{"class":188},"or",[182,564,565],{"class":260}," 0",[182,567,341],{"class":188},[182,569,570],{"class":192}," name ",[182,572,347],{"class":188},[182,574,575],{"class":192}," fields) ",[182,577,364],{"class":188},[182,579,344],{"class":192},[182,581,347],{"class":188},[182,583,584],{"class":192}," regions.getFeatures())\n",[182,586,587],{"class":184,"line":202},[182,588,238],{"emptyLinePlaceholder":237},[182,590,591],{"class":184,"line":208},[182,592,593],{"class":192},"renderer.setClassificationAttributeExpression(\n",[182,595,596,599,602,605,608,610,613,615,617,619,622,624,626,628,630,633,636],{"class":184,"line":221},[182,597,598],{"class":253},"    \"max(\"",[182,600,601],{"class":188}," +",[182,603,604],{"class":253}," \", \"",[182,606,607],{"class":192},".join(",[182,609,324],{"class":188},[182,611,612],{"class":253},"'coalesce(\"",[182,614,330],{"class":260},[182,616,324],{"class":192},[182,618,335],{"class":260},[182,620,621],{"class":253},"\", 0)'",[182,623,341],{"class":188},[182,625,344],{"class":192},[182,627,347],{"class":188},[182,629,575],{"class":192},[182,631,632],{"class":188},"+",[182,634,635],{"class":253}," \")\"",[182,637,455],{"class":192},[182,639,640,643,645],{"class":184,"line":234},[182,641,642],{"class":192},"renderer.setLowerValue(",[182,644,46],{"class":260},[182,646,455],{"class":192},[182,648,649],{"class":184,"line":241},[182,650,651],{"class":192},"renderer.setUpperValue(max_value)\n",[182,653,654,657,659,661,663],{"class":184,"line":266},[182,655,656],{"class":192},"renderer.setLowerSize(QSizeF(",[182,658,46],{"class":260},[182,660,280],{"class":192},[182,662,46],{"class":260},[182,664,665],{"class":192},"))\n",[182,667,668,671,673,675,677,680],{"class":184,"line":298},[182,669,670],{"class":192},"renderer.setUpperSize(QSizeF(",[182,672,46],{"class":260},[182,674,280],{"class":192},[182,676,73],{"class":260},[182,678,679],{"class":192},"))           ",[182,681,682],{"class":437},"# tallest bar: 18 mm\n",[182,684,685],{"class":184,"line":303},[182,686,505],{"class":192},[182,688,689],{"class":184,"line":314},[182,690,511],{"class":192},[182,692,693],{"class":184,"line":353},[182,694,695],{"class":192},"regions.triggerRepaint()\n",[182,697,698,701,703,706],{"class":184,"line":396},[182,699,700],{"class":260},"print",[182,702,553],{"class":192},[182,704,705],{"class":253},"\"tallest bar represents\"",[182,707,708],{"class":192},", max_value)\n",[14,710,711,713],{},[521,712,523],{}," For histogram diagrams, the interpolated size governs bar length: a bar's length is its value divided by the upper value, times the upper size. Starting both value and size at zero keeps lengths proportional — a bar half as long means half the value. Setting the upper value from the data's true maximum, computed across every category of every feature, is what makes bars comparable across the map. Hard-code the upper value instead when several maps must share one scale, for example the same regions in different years.",[150,715,717],{"id":716},"orientation-spacing-and-axes","Orientation, spacing and axes",[14,719,720],{},"Bars can grow up, down, left or right. Upward bars read most naturally; horizontal bars suit features arranged in a north–south band where vertical bars would collide.",[14,722,723],{},[29,724,727,730,733,736,739,742,746,750,754,758,762,765,769,772,775,778,781,786,788,790,794,798,801,804,807],{"viewBox":725,"role":32,"ariaLabel":726,"xmlns":34},"0 0 760 250","Bar diagram orientations up, down, left and right, with an axis line at the base and spacing between bars",[36,728,729],{},"Orientation and axis",[40,731,732],{},"Four orientations: up, down, left and right. Up is the default and reads most naturally. Right suits long horizontal arrangements. An axis line at the base of the bars, available on recent releases, anchors them so readers can see where zero is; spacing between bars keeps adjacent colours distinct.",[44,734],{"x":46,"y":46,"width":47,"height":735,"fill":49},"250",[51,737,738],{"x":53,"y":54,"style":55,"fill":56,"textAnchor":57},"Up is the default; add a base line",[44,740],{"x":61,"y":62,"width":84,"height":741,"rx":65,"fill":66,"stroke":67,"style":68},"150",[44,743],{"x":744,"y":72,"width":745,"height":71,"rx":46,"fill":75,"stroke":75,"style":68},"64","16",[44,747],{"x":748,"y":749,"width":745,"height":85,"rx":46,"fill":80,"stroke":80,"style":68},"84","130",[44,751],{"x":752,"y":741,"width":745,"height":753,"rx":46,"fill":86,"stroke":86,"style":68},"104","30",[184,755],{"x1":756,"y1":757,"x2":749,"y2":757,"stroke":100,"style":68},"56","180",[51,759,761],{"x":752,"y":760,"style":99,"fill":100,"textAnchor":57},"222","up + axis",[44,763],{"x":764,"y":62,"width":84,"height":741,"rx":65,"fill":66,"stroke":67,"style":68},"206",[44,766],{"x":767,"y":768,"width":745,"height":71,"rx":46,"fill":75,"stroke":75,"style":68},"246","80",[44,770],{"x":771,"y":768,"width":745,"height":85,"rx":46,"fill":80,"stroke":80,"style":68},"266",[44,773],{"x":774,"y":768,"width":745,"height":753,"rx":46,"fill":86,"stroke":86,"style":68},"286",[51,776,777],{"x":774,"y":760,"style":99,"fill":100,"textAnchor":57},"down",[44,779],{"x":780,"y":62,"width":84,"height":741,"rx":65,"fill":66,"stroke":67,"style":68},"388",[44,782],{"x":783,"y":784,"width":71,"height":785,"rx":46,"fill":75,"stroke":75,"style":68},"428","90","14",[44,787],{"x":783,"y":72,"width":85,"height":785,"rx":46,"fill":80,"stroke":80,"style":68},[44,789],{"x":783,"y":749,"width":753,"height":785,"rx":46,"fill":86,"stroke":86,"style":68},[51,791,793],{"x":792,"y":760,"style":99,"fill":100,"textAnchor":57},"468","right",[44,795],{"x":796,"y":62,"width":797,"height":741,"rx":65,"fill":66,"stroke":67,"style":68},"570","166",[44,799],{"x":800,"y":784,"width":71,"height":785,"rx":46,"fill":75,"stroke":75,"style":68},"638",[44,802],{"x":803,"y":72,"width":85,"height":785,"rx":46,"fill":80,"stroke":80,"style":68},"658",[44,805],{"x":806,"y":749,"width":753,"height":785,"rx":46,"fill":86,"stroke":86,"style":68},"678",[51,808,810],{"x":809,"y":760,"style":99,"fill":100,"textAnchor":57},"653","left",[172,812,814],{"className":174,"code":813,"language":176,"meta":177,"style":177},"settings.diagramOrientation = QgsDiagramSettings.Up\nsettings.setSpacing(0.4)                        # mm between bars\nsettings.setSpacingUnit(settings.sizeType)      # same unit as sizes\nsettings.setShowAxis(True)\nfrom qgis.core import QgsLineSymbol\nsettings.setAxisLineSymbol(QgsLineSymbol.createSimple({\"color\": \"#2f3b35\", \"width\": \"0.25\"}))\nrenderer.setDiagramSettings(settings)\nregions.triggerRepaint()\n",[179,815,816,826,840,848,858,869,895,899],{"__ignoreMap":177},[182,817,818,821,823],{"class":184,"line":185},[182,819,820],{"class":192},"settings.diagramOrientation ",[182,822,247],{"class":188},[182,824,825],{"class":192}," QgsDiagramSettings.Up\n",[182,827,828,831,834,837],{"class":184,"line":202},[182,829,830],{"class":192},"settings.setSpacing(",[182,832,833],{"class":260},"0.4",[182,835,836],{"class":192},")                        ",[182,838,839],{"class":437},"# mm between bars\n",[182,841,842,845],{"class":184,"line":208},[182,843,844],{"class":192},"settings.setSpacingUnit(settings.sizeType)      ",[182,846,847],{"class":437},"# same unit as sizes\n",[182,849,850,853,856],{"class":184,"line":221},[182,851,852],{"class":192},"settings.setShowAxis(",[182,854,855],{"class":260},"True",[182,857,455],{"class":192},[182,859,860,862,864,866],{"class":184,"line":234},[182,861,189],{"class":188},[182,863,193],{"class":192},[182,865,196],{"class":188},[182,867,868],{"class":192}," QgsLineSymbol\n",[182,870,871,874,877,880,882,884,887,889,892],{"class":184,"line":241},[182,872,873],{"class":192},"settings.setAxisLineSymbol(QgsLineSymbol.createSimple({",[182,875,876],{"class":253},"\"color\"",[182,878,879],{"class":192},": ",[182,881,452],{"class":253},[182,883,280],{"class":192},[182,885,886],{"class":253},"\"width\"",[182,888,879],{"class":192},[182,890,891],{"class":253},"\"0.25\"",[182,893,894],{"class":192},"}))\n",[182,896,897],{"class":184,"line":266},[182,898,505],{"class":192},[182,900,901],{"class":184,"line":298},[182,902,695],{"class":192},[14,904,905,907],{},[521,906,523],{}," A small gap between bars separates adjacent colours, which matters most when two categories have similar hues. The axis line draws a base under the bars, so a missing bar reads as zero rather than as an omission; it was added in the 3.12 series along with bar spacing. Use the same orientation for every diagram on a map; mixing them defeats comparison.",[150,909,911],{"id":910},"make-values-readable","Make values readable",[14,913,914],{},"Bars show relative size; a reader still needs to know what the tallest bar means. A legend entry for size, consistent units and a note on the map close the gap.",[172,916,918],{"className":174,"code":917,"language":176,"meta":177,"style":177},"renderer.setAttributeLegend(True)              # categories in the legend\nprint(f\"tallest bar = {max_value:,.0f} jobs; bars scale linearly from zero\")\n",[179,919,920,933],{"__ignoreMap":177},[182,921,922,925,927,930],{"class":184,"line":185},[182,923,924],{"class":192},"renderer.setAttributeLegend(",[182,926,855],{"class":260},[182,928,929],{"class":192},")              ",[182,931,932],{"class":437},"# categories in the legend\n",[182,934,935,937,939,941,944,946,949,952,954,957],{"class":184,"line":202},[182,936,700],{"class":260},[182,938,553],{"class":192},[182,940,324],{"class":188},[182,942,943],{"class":253},"\"tallest bar = ",[182,945,330],{"class":260},[182,947,948],{"class":192},"max_value",[182,950,951],{"class":188},":,.0f",[182,953,335],{"class":260},[182,955,956],{"class":253}," jobs; bars scale linearly from zero\"",[182,958,455],{"class":192},[14,960,961,963,964,968],{},[521,962,523],{}," With the attribute legend enabled, the layer's legend entry lists each category with its colour, which is all a print legend needs for the colours. For magnitude, the simplest honest device is a sentence in the map's caption — \"tallest bar = 48,200 jobs\" — or a small reference diagram drawn in the layout. ",[21,965,967],{"href":966},"\u002Fpyqgis-cartography-visualization\u002Fdiagrams-and-charts-on-maps\u002Fadd-diagram-legend-and-text-diagrams-pyqgis\u002F","Adding legends for diagrams"," builds a proper size legend.",[150,970,972],{"id":971},"keep-diagrams-readable-at-print-size","Keep diagrams readable at print size",[14,974,975],{},"Diagrams are sized in millimetres, so they look the same on screen and on paper — and what fits on a monitor at one zoom level may be crowded on an A4 export at another scale.",[172,977,979],{"className":174,"code":978,"language":176,"meta":177,"style":177},"from qgis.core import QgsDiagramLayerSettings\n\nls = QgsDiagramLayerSettings()\nls.setPlacement(QgsDiagramLayerSettings.OverPoint)\nls.setShowAllDiagrams(False)\nregions.setDiagramLayerSettings(ls)\n\nsettings.scaleBasedVisibility = True\nsettings.minimumScale = 1_500_000\nrenderer.setDiagramSettings(settings)\nregions.triggerRepaint()\n",[179,980,981,992,996,1006,1011,1021,1026,1030,1039,1049,1053],{"__ignoreMap":177},[182,982,983,985,987,989],{"class":184,"line":185},[182,984,189],{"class":188},[182,986,193],{"class":192},[182,988,196],{"class":188},[182,990,991],{"class":192}," QgsDiagramLayerSettings\n",[182,993,994],{"class":184,"line":202},[182,995,238],{"emptyLinePlaceholder":237},[182,997,998,1001,1003],{"class":184,"line":208},[182,999,1000],{"class":192},"ls ",[182,1002,247],{"class":188},[182,1004,1005],{"class":192}," QgsDiagramLayerSettings()\n",[182,1007,1008],{"class":184,"line":221},[182,1009,1010],{"class":192},"ls.setPlacement(QgsDiagramLayerSettings.OverPoint)\n",[182,1012,1013,1016,1019],{"class":184,"line":234},[182,1014,1015],{"class":192},"ls.setShowAllDiagrams(",[182,1017,1018],{"class":260},"False",[182,1020,455],{"class":192},[182,1022,1023],{"class":184,"line":241},[182,1024,1025],{"class":192},"regions.setDiagramLayerSettings(ls)\n",[182,1027,1028],{"class":184,"line":266},[182,1029,238],{"emptyLinePlaceholder":237},[182,1031,1032,1035,1037],{"class":184,"line":298},[182,1033,1034],{"class":192},"settings.scaleBasedVisibility ",[182,1036,247],{"class":188},[182,1038,477],{"class":260},[182,1040,1041,1044,1046],{"class":184,"line":303},[182,1042,1043],{"class":192},"settings.minimumScale ",[182,1045,247],{"class":188},[182,1047,1048],{"class":260}," 1_500_000\n",[182,1050,1051],{"class":184,"line":314},[182,1052,505],{"class":192},[182,1054,1055],{"class":184,"line":353},[182,1056,695],{"class":192},[14,1058,1059,1061],{},[521,1060,523],{}," Hiding colliding diagrams keeps the map legible; scale-based visibility stops diagrams appearing when the map is zoomed out too far for them to fit. For a print layout at a fixed scale, check the export rather than the canvas — a layout map item renders diagrams at its own scale. If too many diagrams are dropped, reduce the bar width and upper size rather than allowing overlaps.",[150,1063,1065],{"id":1064},"order-and-colour-categories-deliberately","Order and colour categories deliberately",[14,1067,1068,1069,1072],{},"The order of bars is the order of ",[179,1070,1071],{},"categoryAttributes",", and it is the same in every diagram on the map. A deliberate order — by size across the whole dataset, or by a natural sequence such as months or age bands — lets readers learn the pattern once and then scan the map for departures from it.",[14,1074,1075],{},[29,1076,1079,1082,1085,1087,1090,1092,1095,1098,1101,1105,1107,1111,1116,1119,1122,1124,1127,1130,1133,1136,1138,1141,1144,1147],{"viewBox":1077,"role":32,"ariaLabel":1078,"xmlns":34},"0 0 760 230","Bars ordered by overall size form a staircase that makes exceptions stand out, while random order makes every diagram look jagged",[36,1080,1081],{},"A fixed, meaningful order",[40,1083,1084],{},"Bars ordered by overall size, largest first, form a descending staircase in a typical district, so a district where a later bar is taller than an earlier one stands out immediately. Random order produces jagged diagrams in every district, and nothing stands out.",[44,1086],{"x":46,"y":46,"width":47,"height":89,"fill":49},[51,1088,1089],{"x":53,"y":54,"style":55,"fill":56,"textAnchor":57},"Order once, then exceptions stand out",[44,1091],{"x":61,"y":62,"width":63,"height":741,"rx":65,"fill":66,"stroke":67,"style":68},[44,1093],{"x":768,"y":768,"width":1094,"height":74,"rx":46,"fill":80,"stroke":80,"style":68},"22",[44,1096],{"x":1097,"y":72,"width":1094,"height":71,"rx":46,"fill":86,"stroke":86,"style":68},"106",[44,1099],{"x":1100,"y":749,"width":1094,"height":85,"rx":46,"fill":75,"stroke":75,"style":68},"132",[44,1102],{"x":1103,"y":741,"width":1094,"height":753,"rx":46,"fill":1104,"stroke":1104,"style":68},"158","#15803d",[44,1106],{"x":89,"y":768,"width":1094,"height":74,"rx":46,"fill":80,"stroke":80,"style":68},[44,1108],{"x":1109,"y":79,"width":1094,"height":1110,"rx":46,"fill":86,"stroke":86,"style":68},"256","40",[44,1112],{"x":1113,"y":1114,"width":1094,"height":1115,"rx":46,"fill":75,"stroke":75,"style":68},"282","95","85",[44,1117],{"x":1118,"y":741,"width":1094,"height":753,"rx":46,"fill":1104,"stroke":1104,"style":68},"308",[51,1120,1121],{"x":108,"y":760,"style":99,"fill":147,"textAnchor":57},"ordered: the third bar breaks the staircase",[44,1123],{"x":114,"y":62,"width":63,"height":741,"rx":65,"fill":66,"stroke":67,"style":68},[44,1125],{"x":1126,"y":749,"width":1094,"height":85,"rx":46,"fill":75,"stroke":75,"style":68},"452",[44,1128],{"x":1129,"y":768,"width":1094,"height":74,"rx":46,"fill":80,"stroke":80,"style":68},"478",[44,1131],{"x":1132,"y":741,"width":1094,"height":753,"rx":46,"fill":1104,"stroke":1104,"style":68},"504",[44,1134],{"x":1135,"y":72,"width":1094,"height":71,"rx":46,"fill":86,"stroke":86,"style":68},"530",[44,1137],{"x":126,"y":1114,"width":1094,"height":1115,"rx":46,"fill":75,"stroke":75,"style":68},[44,1139],{"x":1140,"y":768,"width":1094,"height":74,"rx":46,"fill":80,"stroke":80,"style":68},"628",[44,1142],{"x":1143,"y":741,"width":1094,"height":753,"rx":46,"fill":1104,"stroke":1104,"style":68},"654",[44,1145],{"x":1146,"y":79,"width":1094,"height":1110,"rx":46,"fill":86,"stroke":86,"style":68},"680",[51,1148,1149],{"x":146,"y":760,"style":99,"fill":67,"textAnchor":57},"random: every diagram looks jagged",[172,1151,1153],{"className":174,"code":1152,"language":176,"meta":177,"style":177},"totals = {f: sum((feat[f] or 0) for feat in regions.getFeatures()) for f in fields}\nordered = sorted(fields, key=lambda f: totals[f], reverse=True)\ncolour_of = dict(zip(fields, settings.categoryColors))\nlabel_of = dict(zip(fields, settings.categoryLabels))\n\nsettings.categoryAttributes = [f'\"{f}\"' for f in ordered]\nsettings.categoryColors = [colour_of[f] for f in ordered]\nsettings.categoryLabels = [label_of[f] for f in ordered]\nrenderer.setDiagramSettings(settings)\nregions.triggerRepaint()\n",[179,1154,1155,1197,1229,1247,1263,1267,1296,1313,1330,1334],{"__ignoreMap":177},[182,1156,1157,1160,1162,1165,1168,1171,1173,1175,1178,1180,1183,1185,1188,1190,1192,1194],{"class":184,"line":185},[182,1158,1159],{"class":192},"totals ",[182,1161,247],{"class":188},[182,1163,1164],{"class":192}," {f: ",[182,1166,1167],{"class":260},"sum",[182,1169,1170],{"class":192},"((feat[f] ",[182,1172,562],{"class":188},[182,1174,565],{"class":260},[182,1176,1177],{"class":192},") ",[182,1179,364],{"class":188},[182,1181,1182],{"class":192}," feat ",[182,1184,347],{"class":188},[182,1186,1187],{"class":192}," regions.getFeatures()) ",[182,1189,364],{"class":188},[182,1191,344],{"class":192},[182,1193,347],{"class":188},[182,1195,1196],{"class":192}," fields}\n",[182,1198,1199,1202,1204,1207,1210,1214,1217,1220,1223,1225,1227],{"class":184,"line":202},[182,1200,1201],{"class":192},"ordered ",[182,1203,247],{"class":188},[182,1205,1206],{"class":260}," sorted",[182,1208,1209],{"class":192},"(fields, ",[182,1211,1213],{"class":1212},"s9osk","key",[182,1215,1216],{"class":188},"=lambda",[182,1218,1219],{"class":192}," f: totals[f], ",[182,1221,1222],{"class":1212},"reverse",[182,1224,247],{"class":188},[182,1226,855],{"class":260},[182,1228,455],{"class":192},[182,1230,1231,1234,1236,1239,1241,1244],{"class":184,"line":208},[182,1232,1233],{"class":192},"colour_of ",[182,1235,247],{"class":188},[182,1237,1238],{"class":260}," dict",[182,1240,553],{"class":192},[182,1242,1243],{"class":260},"zip",[182,1245,1246],{"class":192},"(fields, settings.categoryColors))\n",[182,1248,1249,1252,1254,1256,1258,1260],{"class":184,"line":221},[182,1250,1251],{"class":192},"label_of ",[182,1253,247],{"class":188},[182,1255,1238],{"class":260},[182,1257,553],{"class":192},[182,1259,1243],{"class":260},[182,1261,1262],{"class":192},"(fields, settings.categoryLabels))\n",[182,1264,1265],{"class":184,"line":234},[182,1266,238],{"emptyLinePlaceholder":237},[182,1268,1269,1271,1273,1275,1277,1279,1281,1283,1285,1287,1289,1291,1293],{"class":184,"line":241},[182,1270,317],{"class":192},[182,1272,247],{"class":188},[182,1274,274],{"class":192},[182,1276,324],{"class":188},[182,1278,327],{"class":253},[182,1280,330],{"class":260},[182,1282,324],{"class":192},[182,1284,335],{"class":260},[182,1286,338],{"class":253},[182,1288,341],{"class":188},[182,1290,344],{"class":192},[182,1292,347],{"class":188},[182,1294,1295],{"class":192}," ordered]\n",[182,1297,1298,1300,1302,1305,1307,1309,1311],{"class":184,"line":266},[182,1299,356],{"class":192},[182,1301,247],{"class":188},[182,1303,1304],{"class":192}," [colour_of[f] ",[182,1306,364],{"class":188},[182,1308,344],{"class":192},[182,1310,347],{"class":188},[182,1312,1295],{"class":192},[182,1314,1315,1317,1319,1322,1324,1326,1328],{"class":184,"line":298},[182,1316,399],{"class":192},[182,1318,247],{"class":188},[182,1320,1321],{"class":192}," [label_of[f] ",[182,1323,364],{"class":188},[182,1325,344],{"class":192},[182,1327,347],{"class":188},[182,1329,1295],{"class":192},[182,1331,1332],{"class":184,"line":303},[182,1333,505],{"class":192},[182,1335,1336],{"class":184,"line":314},[182,1337,695],{"class":192},[14,1339,1340,1342],{},[521,1341,523],{}," Ordering by each category's total across all features makes the typical diagram a descending staircase, so any region whose bars break the staircase — services larger than industry where industry usually dominates — is visible at a glance. Colours travel with their categories through the reordering, so the same sector keeps the same colour on every map in a series. For naturally ordered categories, such as months or age groups, keep the natural order instead.",[150,1344,1346],{"id":1345},"bars-versus-other-diagram-types","Bars versus other diagram types",[14,1348,1349,1350,1354,1355,1359],{},"Histogram diagrams are the right choice when readers should compare the same category between features — industrial jobs here versus there — or compare categories with each other in absolute terms. When the whole matters as much as the parts, ",[21,1351,1353],{"href":1352},"\u002Fpyqgis-cartography-visualization\u002Fdiagrams-and-charts-on-maps\u002Fadd-stacked-bar-diagrams-pyqgis\u002F","stacked bar diagrams"," show the total as one bar divided into segments. When only proportions matter, ",[21,1356,1358],{"href":1357},"\u002Fpyqgis-cartography-visualization\u002Fdiagrams-and-charts-on-maps\u002Fadd-pie-chart-diagrams-pyqgis\u002F","pies"," are more compact. With more than five or six categories, no diagram type remains readable at map size — group categories, or move the detail into a chart beside the map.",[150,1361,1363],{"id":1362},"qgis-version-compatibility","QGIS version compatibility",[14,1365,1366,1369,1370,1373,1374,1377],{},[179,1367,1368],{},"QgsHistogramDiagram"," and the interpolated renderer work on QGIS 3.34 LTR, 3.40 LTR and QGIS 4. Axis lines and bar spacing require 3.12 or newer. On QGIS 4, orientation is ",[179,1371,1372],{},"QgsDiagramSettings.DiagramOrientation.Up"," and placement is ",[179,1375,1376],{},"QgsDiagramLayerSettings.Placement.OverPoint",".",[150,1379,1381],{"id":1380},"troubleshooting","Troubleshooting",[155,1383,1384,1390,1400,1406],{},[158,1385,1386,1389],{},[521,1387,1388],{},"All bars have the same length."," The renderer is single-category with a fixed size; use the interpolated renderer with a shared upper value.",[158,1391,1392,1395,1396,1399],{},[521,1393,1394],{},"Bars exceed the upper size."," A value is larger than ",[179,1397,1398],{},"setUpperValue","; recompute the maximum across all categories.",[158,1401,1402,1405],{},[521,1403,1404],{},"Diagrams disappear when zoomed out."," Scale-based visibility is hiding them, or collisions are dropping them.",[158,1407,1408,1411,1412,1415,1416,1377],{},[521,1409,1410],{},"Bars are invisible on a pale base."," Add an outline with ",[179,1413,1414],{},"penColor"," and ",[179,1417,1418],{},"penWidth",[150,1420,1422],{"id":1421},"conclusion","Conclusion",[14,1424,1425,1426,1428],{},"Use ",[179,1427,1368],{}," with the linearly interpolated renderer, set the upper value to the largest category value across all features so bars share one scale, keep zero as the base, add spacing and an axis line, state what the tallest bar represents, and manage collisions and scale ranges for print.",[150,1430,1432],{"id":1431},"frequently-asked-questions","Frequently Asked Questions",[14,1434,1435,1438],{},[521,1436,1437],{},"Why is it called a histogram?","\nQGIS's naming; it draws one bar per category, which is a bar chart rather than a frequency histogram.",[14,1440,1441,1444],{},[521,1442,1443],{},"Can bars show negative values?","\nNot meaningfully; bar length is derived from the value's ratio to the upper value. Show change with a diverging choropleth instead.",[14,1446,1447,1450],{},[521,1448,1449],{},"Can each bar have a label with its value?","\nNot directly. Use a text diagram or labels with an expression next to the diagram.",[14,1452,1453,1456],{},[521,1454,1455],{},"Can I use the same scale on maps of different years?","\nYes — set the upper value to the maximum over all years and reuse it.",[150,1458,1460],{"id":1459},"related","Related",[155,1462,1463,1468,1473,1478,1484],{},[158,1464,1465,1467],{},[21,1466,24],{"href":23}," — the guide this recipe belongs to",[158,1469,1470],{},[21,1471,1472],{"href":1357},"Add Pie Chart Diagrams to a Layer in PyQGIS",[158,1474,1475],{},[21,1476,1477],{"href":1352},"Add Stacked Bar Diagrams in PyQGIS",[158,1479,1480],{},[21,1481,1483],{"href":1482},"\u002Fpyqgis-cartography-visualization\u002Fdiagrams-and-charts-on-maps\u002Fsize-diagrams-by-attribute-pyqgis\u002F","Size Diagrams by Attribute in PyQGIS",[158,1485,1486],{},[21,1487,1489],{"href":1488},"\u002Fspatial-data-processing-automation\u002Fautomated-map-layout-generation\u002Fadd-legend-to-layout-pyqgis\u002F","Add a Legend to a Print Layout in PyQGIS",[1491,1492,1493],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sjoCn, html code.shiki .sjoCn{--shiki-default:#9AA79F}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":177,"searchDepth":202,"depth":202,"links":1495},[1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508],{"id":152,"depth":202,"text":153},{"id":166,"depth":202,"text":167},{"id":531,"depth":202,"text":532},{"id":716,"depth":202,"text":717},{"id":910,"depth":202,"text":911},{"id":971,"depth":202,"text":972},{"id":1064,"depth":202,"text":1065},{"id":1345,"depth":202,"text":1346},{"id":1362,"depth":202,"text":1363},{"id":1380,"depth":202,"text":1381},{"id":1421,"depth":202,"text":1422},{"id":1431,"depth":202,"text":1432},{"id":1459,"depth":202,"text":1460},"Draw small bar charts on map features with QgsHistogramDiagram — bars from fields or expressions, a shared scale so bars compare across features, orientation, bar width and spacing, axis lines, and labels that stay readable at print size.","md",{"slug":1512,"type":1513,"breadcrumb":1514,"datePublished":1515,"dateModified":1515},"add-histogram-bar-diagrams-pyqgis","article","Add Histogram Bar Diagrams","2026-10-02","\u002Fpyqgis-cartography-visualization\u002Fdiagrams-and-charts-on-maps\u002Fadd-histogram-bar-diagrams-pyqgis",{"title":5,"description":1509},"pyqgis-cartography-visualization\u002Fdiagrams-and-charts-on-maps\u002Fadd-histogram-bar-diagrams-pyqgis\u002Findex","U_PCGGBR6huhoc2w7E-A_2BwnebRyBbVEccFs_modUg",1790966252898]