24 用annotation属性画了条直线的柱形图(BarChart)
-
数据柱旁边的标签是垂直的:chart.barLabels.angle=90
-
类别轴属性labelAxisMode(categoryAxis.labelAxisMode)设置类别坐标轴的标签位置
-
用annotation属性画了一条直线
代码和注释:
"Vertical labels"
from reportlab.lib.colors import PCMYKColor, black, red
from reportlab.graphics.charts.legends import Legend
from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String, Line
from reportlab.lib.validators import Auto
from reportlab.lib.formatters import DecimalFormatter
from reportlab.graphics.charts.barcharts import VerticalBarChart
class BarChart_VLabelsAnnotation(_DrawingEditorMixin,Drawing):
def __init__(self,width=348,height=146,*args,**kw):
Drawing.__init__(self,width,height,*args,**kw)
fontName = 'Helvetica'
# 添加垂直的直方图
self._add(self,VerticalBarChart(),name='chart',validate=None,desc=None)
# 直方图设置
self.chart.width = self.width - self.chart.x
self.chart.height = self.height - self.chart.y - 20
self.chart.groupSpacing = 20 # 组间距
self.chart.barSpacing = 1 # 组内间距
self.chart.bars.strokeWidth = 0 # 柱周线宽度
self.chart.bars.strokeColor = None # 柱周线颜色
# 柱标签
self.chart.barLabels.angle = 90 # 柱标签旋转90度
self.chart.barLabelFormat = DecimalFormatter(2) # 柱标签两位小数点
self.chart.barLabels.boxAnchor ='w' # 锚点在西
self.chart.barLabels.boxFillColor = None # 柱标签没有填充色
# self.chart.barLabels.boxFillColor = red
self.chart.barLabels.boxStrokeColor= None # 柱标签周线没有颜色
# self.chart.barLabels.boxStrokeColor= red
self.chart.barLabels.fontName = fontName
self.chart.barLabels.fontSize = 5
self.chart.barLabels.dy = 3 # 向上微调柱标签的位置
self.chart.barLabels.boxTarget = 'hi' # 柱标签标在数据柱上
# self.chart.barLabels.boxTarget = 'lo' # 柱标签标在数据柱下
# self.chart.barLabels.boxTarget = 'anti' # 坐标轴上下,正上负下
# self.chart.barLabels.boxTarget = 'normal' # 柱旁,正上负下
# 数值轴(y轴)
self.chart.valueAxis.labels.fontName = fontName
self.chart.valueAxis.labels.fontSize = 8
self.chart.valueAxis.strokeWidth = 0.25
self.chart.valueAxis.avoidBoundFrac = 0.5 # 影响数值轴上数据范围
self.chart.valueAxis.rangeRound ='both'
# 如何截数值轴的上下值,ceiling(往大了截)还是floor(往小了截),或者两者兼顾both
self.chart.valueAxis.visibleGrid = False # y轴出发的格子线不可见
self.chart.valueAxis.labelTextFormat = DecimalFormatter(0, suffix=None, prefix=None)
# y轴上刻度值的格式,小数点为0位
self.chart.valueAxis.labels.boxAnchor='e' # 锚点在东
self.chart.valueAxis.labels.dx = -1 # y轴刻度标签向左微调1
self.chart.valueAxis.visibleTicks = 0 # 刻度线不可见
# 类别轴(x轴)
self.chart.categoryAxis.strokeWidth = 0.25
self.chart.categoryAxis.visibleGrid = False
self.chart.categoryAxis.visibleTicks = True # x轴上刻度线可见
self.chart.categoryAxis.tickUp = 3 # 刻度线向上伸出3
self.chart.categoryAxis.tickDown = 0 # 刻度线向下伸出0
self.chart.categoryAxis.labelAxisMode ='low'
# 刻度标签在整个图表的底部
# self.chart.categoryAxis.labelAxisMode ='high'
# 刻度标签在整个图表的顶部
# self.chart.categoryAxis.labelAxisMode ='axis'
# 刻度标签在坐标轴旁
# self.chart.categoryAxis.labelAxisMode ='axispmv'
# 刻度标签在坐标轴旁,在上在下看数据柱的主要朝向
self.chart.categoryAxis.labels.textAnchor = 'middle' # 文字居中
self.chart.categoryAxis.labels.boxAnchor = 'n' # 锚点在北
self.chart.categoryAxis.labels.fillColor = black
self.chart.categoryAxis.labels.angle = 0
self.chart.categoryAxis.labels.fontName = fontName
self.chart.categoryAxis.labels.fontSize = 7
self.chart.categoryAxis.labels.dx = 0 # 刻度标签微调位移
self.chart.categoryAxis.labels.dy = -2
self.chart.categoryAxis.categoryNames = ['Quarter', 'YTD', '1-year', '3-year', '5-year']
# 刻度标签内容
# 图例
self._add(self,Legend(),name='legend',validate=None,desc=None)
self.legend.boxAnchor = 'nw'
self.legend.deltax = 0
self.legend.deltay = 10
self.legend.columnMaximum = 3
self.legend.fontName = fontName
self.legend.fontSize = 6
self.legend.alignment = 'right'
self.legend.strokeWidth = 0
self.legend.strokeColor = None
self.legend.autoXPadding = 0
self.legend.dx = 7
self.legend.dy = 7
self.legend.dxTextSpace = 7
self.legend.variColumn = True
self.legend.subCols.minWidth = self.chart.width/2
self.chart.data = [[-9.0299999999999994, -9.0299999999999994, -4.5800000000000001, 7.2699999999999996, 11.109999999999999],
[-9.4399999999999995, -9.4399999999999995, -5.0700000000000003, 5.8499999999999996, 0.0],
[2.1699999999999999, 2.1699999999999999, 7.6600000000000001, 0.0, 4.5800000000000001],
[-5.1399999999999997, -5.1399999999999997, 0.0, 8.1699999999999999, 11.380000000000001],
[-4.8799999999999999, -4.8799999999999999, 0.02, 5.8099999999999996, 8.6999999999999993]]
series = 'BP', 'Shell Transport & Trading', 'Liberty International', 'Persimmon', 'Royal Bank of Scotland',
for i, s in enumerate(series):
self.chart.bars[i].name = s # 每个数据柱代表的意义
self.legend.colorNamePairs = Auto(obj=self.chart)
# 开启自动模式,生成图例色块与名字的一一对应
# 指定每个数据柱颜色
colorsList = [PCMYKColor(23,51,0,4,spotName='XXX X',alpha=100), PCMYKColor(100,60,0,50,spotName='7475C',alpha=100),
PCMYKColor(100,0,90,50,spotName='7475C',density=40,alpha=100), PCMYKColor(0,100,100,40,spotName='XXX X',alpha=100),
PCMYKColor(66,13,0,22,spotName='XXX X',alpha=100), PCMYKColor(0,0,0,40,spotName='XXX X',alpha=100), PCMYKColor(50,0,25,30,spotName='7475C',density=25,alpha=100), PCMYKColor(0,0,0,25,spotName='XXX X',alpha=100)]
for i, _ in enumerate(self.chart.data):
self.chart.bars[i].fillColor = colorsList[i]
# 在图表底部加一条直线
self.chart.annotations=[lambda c,cA,vA: Line(c.x,c.y,c.x+c.width,c.y,strokeColor=black,strokeWidth=0.5)]
# 属性annotations的使用参见帖子28 图表的annotation属性
self.width = 400
self.height = 200
self.chart.x = 30
self.chart.y = 60
self.legend.x = 35
self.legend.y = 35
if __name__=="__main__":
BarChart_VLabelsAnnotation().save(formats=['pdf'],outDir='.',fnRoot=None)