Remove Tick marks in Line chart, APACHE POI - excel

I've generated a line chart using Apache poi. There are 400 values in the X axis and the tick marks make some values unclear as there is lot of tick marks there. Therefore, I need to remove the tick marks in X axis. Is there any way to remove them?
My code is as follows.
Drawing drawing = sheet4.createDrawingPatriarch();
ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 1, 1, 17, 22);
Chart chart = drawing.createChart(anchor);
ChartLegend legend = chart.getOrCreateLegend();
legend.setPosition(LegendPosition.RIGHT);
LineChartData data = chart.getChartDataFactory().createLineChartData();
ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM);
ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
ChartDataSource<Number> xs = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(1, 380, 0, 0));
ChartDataSource<Number> ys1 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(1, 380, 1, 1));
ChartDataSource<Number> ys2 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(1, 380, 3, 3));
ChartDataSource<Number> ys3 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(1, 380, 4, 4));
ChartDataSource<Number> ys4 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(1, 380, 8, 8));
LineChartSeries series1 = data.addSeries(xs, ys1);
series1.setTitle("Value 1");
LineChartSeries series2 = data.addSeries(xs, ys2);
series2.setTitle("Value 2");
LineChartSeries series3 = data.addSeries(xs, ys3);
series3.setTitle("Value 3");
LineChartSeries series4 = data.addSeries(xs, ys4);
series4.setTitle("Value 4");
chart.plot(data, bottomAxis, leftAxis);
XSSFChart xssfChart = (XSSFChart) chart;
CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea();
plotArea.getLineChartArray()[0].getSmooth();
CTBoolean ctBool = CTBoolean.Factory.newInstance();
ctBool.setVal(false);
plotArea.getLineChartArray()[0].setSmooth(ctBool);
for (CTLineSer ser : plotArea.getLineChartArray()[0].getSerArray()) {
ser.setSmooth(ctBool);
}

For newer POI versions , we could remove the marker style using:
series1.setMarkerStyle(MarkerStyle.NONE);
Additional Info:
In addition to that it support different marker styles:
MarkerStyle.CIRCLE
MarkerStyle.DASH
MarkerStyle.DIAMOND
MarkerStyle.DOT
MarkerStyle.PICTURE
MarkerStyle.PLUS
MarkerStyle.SQUARE
MarkerStyle.STAR
MarkerStyle.TRIANGLE
I'm using the library version : 4.1.2.

Related

Can't get attribute location pyglet

this code doesn't allow me to use it
position_loc = glGetAttribLocation(shader, "position")
color_loc = glGetAttribLocation(shader, "color")
the full code near it
shader = OpenGL.GL.shaders.compileProgram(OpenGL.GL.shaders.compileShader(self.vertex_shader_source, GL_VERTEX_SHADER),
OpenGL.GL.shaders.compileShader(self.fragment_shader_source, GL_FRAGMENT_SHADER))
position_loc = glGetAttribLocation(shader, "position")
color_loc = glGetAttribLocation(shader, "color")
glUseProgram(shader)
vbo = GLuint(0)
glGenBuffers(1, vbo)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, 72, (GLfloat * len(self.triangle))(* self.triangle), GL_STATIC_DRAW)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(12))
glEnableVertexAttribArray(1)
this is all the code aside from the shaders, which is in another question of mine. it works fine if i don't get the locations, but i was told i need to. if you could help me understand why it isn't working that would be awesome
The name argument needs to be a Bytes literal (bytesprefix b) rather than a string:
position_loc = glGetAttribLocation(shader, 'position')
color_loc = glGetAttribLocation(shader, 'color')
position_loc = glGetAttribLocation(shader, b'position')
color_loc = glGetAttribLocation(shader, b'color')

How to add Vertical Line to a Bar Chart using POI 4.0.1 Java

How do you add vertical line to a bar chart(horizontal) using POI. I am trying to add a line similar to this orange vertical line.
Bar chart + vertical line
Referred here for manual MS Excel working
https://www.extendoffice.com/documents/excel/2344-excel-add-vertical-line-to-bar-chart.html
I have referred this answer for combining column chart with a horizontal line chart
https://stackoverflow.com/a/47080178/9693259
To create this graph
Column chart + horizontal line
I have changed the column chart to be a bar chart
Bar chart + horizontal line
But I cannot find how to change the orientation of the line chart like I did with the column to bar.
Bar chart has category axis on left, value axis on bottom.
Line chart only accepts category axis on bottom.
Edit:
Attempt at Bar chart + Line chart
If you read your linked How to add vertical/average line to bar chart in Excel? correct, then you will see, that there is bar chart and scatter chart combined and not bar chart and line chart. This is because the average value must be on X axis of the chart and only scatter chart is able displaying decimal values on X axis. For all other charts, the X axis is a category axis.
So to create the same as in the linked article using apache poi we can do it like this using the low level underlying ooxml beans (ooxml-schemas-*.jar must be in class path):
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.charts.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
public class BarAndScatterChartLowLevel {
public static void main(String[] args) throws Exception {
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("Sheet1");
Row row;
Cell cell;
row = sheet.createRow(0);
row.createCell(0);
row.createCell(1).setCellValue("Bars");
for (int r = 1; r < 7; r++) {
row = sheet.createRow(r);
cell = row.createCell(0);
cell.setCellValue("C" + r);
cell = row.createCell(1);
cell.setCellFormula("RANDBETWEEN(5, 10)/10");
}
row = sheet.createRow(7);
row.createCell(0).setCellValue("Average");
row = sheet.createRow(8);
row.createCell(0).setCellValue("Y");
row.createCell(1).setCellValue("X");
row = sheet.createRow(9);
row.createCell(0).setCellValue(0);
row.createCell(1).setCellFormula("AVERAGE($B$2:$B$7)");
row = sheet.createRow(10);
row.createCell(0).setCellValue(1);
row.createCell(1).setCellFormula("AVERAGE($B$2:$B$7)");
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 4, 0, 11, 15);
XSSFChart chart = ((XSSFDrawing)drawing).createChart(anchor);
CTChart ctChart = chart.getCTChart();
CTPlotArea ctPlotArea = ctChart.getPlotArea();
//the bar chart
CTBarChart ctBarChart = ctPlotArea.addNewBarChart();
CTBoolean ctBoolean = ctBarChart.addNewVaryColors();
ctBoolean.setVal(true);
ctBarChart.addNewBarDir().setVal(STBarDir.BAR);
//the bar series
CTBarSer ctBarSer = ctBarChart.addNewSer();
CTSerTx ctSerTx = ctBarSer.addNewTx();
CTStrRef ctStrRef = ctSerTx.addNewStrRef();
ctStrRef.setF("Sheet1!$B$1");
ctBarSer.addNewIdx().setVal(0);
CTAxDataSource cttAxDataSource = ctBarSer.addNewCat();
ctStrRef = cttAxDataSource.addNewStrRef();
ctStrRef.setF("Sheet1!$A$2:$A$7");
CTNumDataSource ctNumDataSource = ctBarSer.addNewVal();
CTNumRef ctNumRef = ctNumDataSource.addNewNumRef();
ctNumRef.setF("Sheet1!$B$2:$B$7");
//telling the BarChart that it has axes and giving them Ids
ctBarChart.addNewAxId().setVal(123456); //cat axis 1 (bars)
ctBarChart.addNewAxId().setVal(123457); //val axis 1 (left)
//the scatter chart
CTScatterChart ctScatterChart = ctPlotArea.addNewScatterChart();
ctBoolean = ctScatterChart.addNewVaryColors();
ctBoolean.setVal(true);
//the scatter series
CTScatterSer ctScatterSer = ctScatterChart.addNewSer();
ctSerTx = ctScatterSer.addNewTx();
ctStrRef = ctSerTx.addNewStrRef();
ctStrRef.setF("Sheet1!$A$8");
ctScatterSer.addNewIdx().setVal(1);
cttAxDataSource = ctScatterSer.addNewXVal();
ctStrRef = cttAxDataSource.addNewStrRef();
ctStrRef.setF("Sheet1!$B$10:$B$11");
ctNumDataSource = ctScatterSer.addNewYVal();
ctNumRef = ctNumDataSource.addNewNumRef();
ctNumRef.setF("Sheet1!$A$10:$A$11");
//telling the ScatterChart that it has axes and giving them Ids
ctScatterChart.addNewAxId().setVal(123458); //cat axis 2 (scatter)
ctScatterChart.addNewAxId().setVal(123459); //val axis 2 (right)
//cat axis 1 (bars)
CTCatAx ctCatAx = ctPlotArea.addNewCatAx();
ctCatAx.addNewAxId().setVal(123456); //id of the cat axis
CTScaling ctScaling = ctCatAx.addNewScaling();
ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
ctCatAx.addNewDelete().setVal(false);
ctCatAx.addNewAxPos().setVal(STAxPos.B);
ctCatAx.addNewCrossAx().setVal(123457); //id of the val axis
ctCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);
//val axis 1 (left)
CTValAx ctValAx = ctPlotArea.addNewValAx();
ctValAx.addNewAxId().setVal(123457); //id of the val axis
ctScaling = ctValAx.addNewScaling();
ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
ctValAx.addNewDelete().setVal(false);
ctValAx.addNewAxPos().setVal(STAxPos.L);
ctValAx.addNewCrossAx().setVal(123456); //id of the cat axis
ctValAx.addNewCrosses().setVal(STCrosses.AUTO_ZERO); //this val axis crosses the cat axis at zero
ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);
//cat axis 2 (scatter)
ctCatAx = ctPlotArea.addNewCatAx();
ctCatAx.addNewAxId().setVal(123458); //id of the cat axis
ctScaling = ctCatAx.addNewScaling();
ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
ctCatAx.addNewDelete().setVal(true); //this cat axis is deleted
ctCatAx.addNewAxPos().setVal(STAxPos.B);
ctCatAx.addNewCrossAx().setVal(123459); //id of the val axis
ctCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);
//val axis 2 (right)
ctValAx = ctPlotArea.addNewValAx();
ctValAx.addNewAxId().setVal(123459); //id of the val axis
ctScaling = ctValAx.addNewScaling();
ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
ctScaling.addNewMax().setVal(1.0);
ctValAx.addNewDelete().setVal(false);
ctValAx.addNewAxPos().setVal(STAxPos.R);
ctValAx.addNewCrossAx().setVal(123458); //id of the cat axis
ctValAx.addNewCrosses().setVal(STCrosses.MAX); //this val axis crosses the cat axis at max value
ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);
//legend
CTLegend ctLegend = ctChart.addNewLegend();
ctLegend.addNewLegendPos().setVal(STLegendPos.B);
ctLegend.addNewOverlay().setVal(false);
FileOutputStream fileOut = new FileOutputStream("BarAndScatterChart.xlsx");
wb.write(fileOut);
fileOut.close();
wb.close();
}
}
But since apache poi 4.0.1 provides the XDDF stuff now, the same could be done as follows:
import java.io.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
public class BarAndScatterChart {
public static void main(String[] args) throws IOException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
// Create the data
XSSFSheet sheet = wb.createSheet("Sheet1");
Row row;
Cell cell;
row = sheet.createRow(0);
row.createCell(0);
row.createCell(1).setCellValue("Bars");
for (int r = 1; r < 7; r++) {
row = sheet.createRow(r);
cell = row.createCell(0);
cell.setCellValue("C" + r);
cell = row.createCell(1);
cell.setCellFormula("RANDBETWEEN(5, 10)/10");
}
row = sheet.createRow(7);
row.createCell(0).setCellValue("Average");
row = sheet.createRow(8);
row.createCell(0).setCellValue("Y");
row.createCell(1).setCellValue("X");
row = sheet.createRow(9);
row.createCell(0).setCellValue(0);
row.createCell(1).setCellFormula("AVERAGE($B$2:$B$7)");
row = sheet.createRow(10);
row.createCell(0).setCellValue(1);
row.createCell(1).setCellFormula("AVERAGE($B$2:$B$7)");
// create data sources
XDDFDataSource<String> cat = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(1, 6, 0, 0));
XDDFNumericalDataSource<Double> barVal = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 6, 1, 1));
XDDFDataSource<Double> scatterX = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(9, 10, 1, 1));
XDDFNumericalDataSource<Double> scatterY = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(9, 10, 0, 0));
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 4, 0, 11, 15);
XSSFChart chart = drawing.createChart(anchor);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.BOTTOM);
// bar chart
// Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
XDDFChartData.Series series1 = data.addSeries(cat, barVal);
series1.setTitle("bars", new CellReference(sheet.getSheetName(), 0, 1, true, true));
chart.plot(data);
// in order to transform a bar chart into a column chart, you just need to change the bar direction
XDDFBarChartData bar = (XDDFBarChartData) data;
bar.setBarDirection(BarDirection.BAR);
solidFillSeries(data, 0, PresetColor.CHARTREUSE);
// scatter chart
// axis must be there but must not be visible
bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setVisible(false);
// right axis for scatter chart
XDDFValueAxis rightAxis = chart.createValueAxis(AxisPosition.RIGHT);
rightAxis.setCrosses(AxisCrosses.MAX);
rightAxis.setMaximum(1.0);
// set correct cross axis
bottomAxis.crossAxis(rightAxis);
rightAxis.crossAxis(bottomAxis);
data = chart.createData(ChartTypes.SCATTER, bottomAxis, rightAxis);
XDDFScatterChartData.Series series2 = (XDDFScatterChartData.Series)data.addSeries(scatterX, scatterY);
series2.setTitle("average", new CellReference(sheet.getSheetName(), 7, 0, true, true));
series2.setSmooth(false);
chart.plot(data);
// correct the id and order, must not be 0 again because there is one bar series already
chart.getCTChart().getPlotArea().getScatterChartArray(0).getSerArray(0).getIdx().setVal(1);
chart.getCTChart().getPlotArea().getScatterChartArray(0).getSerArray(0).getOrder().setVal(1);
solidLineSeries(data, 0, PresetColor.BLUE);
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("ooxml-bar-and-scatter-chart.xlsx")) {
wb.write(fileOut);
}
}
}
private static void solidFillSeries(XDDFChartData data, int index, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFChartData.Series series = data.getSeries().get(index);
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setFillProperties(fill);
series.setShapeProperties(properties);
}
private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFLineProperties line = new XDDFLineProperties();
line.setFillProperties(fill);
XDDFChartData.Series series = data.getSeries().get(index);
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setLineProperties(line);
series.setShapeProperties(properties);
}
}

How to do a threshold line on a bar chart using plotly

Currently written this code that produces a bar chart but would like to add a threshold line. Could anyone help me please?
def make_bar_chart(data):
"""Takes a list of dicts with a time and price"""
# Times
chart_x = []
# Prices
chart_y = []
# Create the relevant arrays
for item in data:
chart_x.append(item["time"])
chart_y.append(item["price"])
# Make the chart
the_graph = Bar(x = chart_x, y = chart_y , name = "Stocks")
graph_data = Data([the_graph])
the_layout = Layout(title = "Stocks", xaxis = dict(title = "Time"), yaxis = dict(title = "Price"))
the_figure = Figure(data = graph_data, layout = the_layout)
plotly.offline.plot(the_figure, filename = "stocks.html")
Try something like this. In plotly it seems that lines are provided via shapes.
the_layout = Layout(title = "Stocks",
xaxis = dict(title = "Time"),
yaxis = dict(title = "Price"),
shapes=[
{
'type': 'line',
'xref': 'paper',
'x0': 0,
'y0': 100, # use absolute value or variable here
'x1': 1,
'y1': 100, # ditto
'line': {
'color': 'rgb(50, 171, 96)',
'width': 1,
'dash': 'dash',
},
},
],
)
I haven't tested this as you haven't provided sample data. Well done for supplying code on your first question, but on Stack Overflow it's best to provide a completely self-contained example that people can copy and run 'as is.'

Draw line with d3.js using separate, fixed x & y input arrays

I have separate x and y arrays and want to connect the dots using a line path. This seems to be about the simplest possible example but I don't quite grok the writing the function. Here is my code:
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src = "http://d3js.org/d3.v3.min.js"> </script>
<script>
var margin = {top: 20, right: 20, bottom: 20, left: 20},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
var xdata = d3.range(20);
var ydata = [1, 4, 5, 9, 10, 14, 15, 15, 11, 10, 5, 5, 4, 8, 7, 5, 5, 5, 8, 10];
var xscl = d3.scale.linear()
.domain(d3.extent(xdata))
.range([0, width])
var yscl = d3.scale.linear()
.domain(d3.extent(ydata))
.range([height, 0])
var slice = d3.svg.line()
.x(function(d) { return xscl(xdata[d]);})
.y(function(d) { return yscl(ydata[d]);})
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
svg.append("path")
.attr("class", "line")
.attr("d", slice)
</script>
</body>
But it returns an error Uncaught TypeError: Cannot read property 'length' of undefined, so clearly the function returned by d3.svg.line() doesn't have the right form. What's wrong? I pray not a typo!
I know it has been more than a year, but I had to deal with this problem also.
Storing path data (x, y) in 2 separate arrays is much more memory efficient than the 2D array d3.svg.line expects. For a very large number of points, the accepted answer is also inefficient by looping through all elements to create the 2D array.
The solution I found without adding any loops is write a wrapper function for d3.svg.line as follows:
var line = function(x, y){
return d3.svg.line()
.x(function(d,i) { return x[i]; })
.y(function(d,i) { return y[i]; })
(Array(x.length));
}
and then set the path attributes:
svg.append("path")
.attr("d", line(x_array, y_array))
See the updated fiddle here
Based on Elijah's spot on remark about d3.svg.line, I think it is hard to go about this without putting the array as expected by this function. So:
var xy = [];
for(var i=0;i<xdata.length;i++){
xy.push({x:xdata[i],y:ydata[i]});
}
I made other changes regarding .domain and the slice function per se. Here is a FIDDLE with the results of my effort.
d3.svg.line can only take one data source. However, you can feed it your two data sources by putting them into an object:
newData = {x: xdata, y: ydata};
var slice = d3.svg.line()
.x(function(d,i) { return xscl(d.xdata[i]);})
.y(function(d,i) { return yscl(d.ydata[i]);})
Then point your line function at newData and you should be set:
svg.append("path")
.attr("class", "line")
.attr("d", slice(newData))
Typically, though, you're better off building an array of coordinate pairs, since that's what it's expecting.

Displaying totals above stacked bars in barchart: matplotlib.pyplot

I am just starting out with matplotlib.pyplot and am a little stuck.
Using the example in the matpltlib.pyplot documentation, I have created a stacked bar chart using the following code:
import numpy as np
import matplotlib.pyplot as plt
N = 7
OECD = (242, 244, 255, 263, 269, 276, 285)
NonOECD = (282, 328, 375, 417, 460, 501, 535)
Sum = ('524', '572', '630', '680', '729', '777', '820')
ind = np.arange(N)
width = 0.5
p1 = plt.bar(ind, NonOECD, width, color = 'r')
p2 = plt.bar(ind, OECD, width, color = 'b', bottom = NonOECD)
plt.ylabel('Quadrillion Btu')
plt.title('World Total Energy Consumption 2010 - 2040')
plt.xticks(ind+width/2., ('2010', '2015', '2020', '2025', '2030', '2035', '2040'))
plt.yticks(np.arange(0, 1001, 200))
plt.legend((p1[0], p2[0]), ('Non - OECD', 'OECD'), loc = 2, frameon = 'false')
plt.tick_params(top = 'off', bottom = 'off', right = 'off')
plt.grid(axis = 'y', linestyle = '-')
plt.show()
However I want to display the totals on top of the bars and I cannot quite work out how. I have seen this post but am having issues:
for ii,rect in enumerate(p1):
h1 = rect.get_height()
for ii,rect in enumerate(p2):
h2 = rect.get_height()
height =
plt.text(rect.get_x()+rect.get_width()/2., height, '%s'% (Sum[ii]), ha = 'center', va='bottom')
If I use height = h1 I get ; if I use height = h2 I get ; if I use height = h1 + h2 I get .
What I want is these numbers sitting directly on above the second (blue) bar [like the 524 on the 2010 bar in my 1st attempt]. Am I missing something really obvious?
As always, any help would be much appreciated!
Cheers
Try this:
for r1,r2 in zip(p1,p2):
h1 = r1.get_height()
h2 = r2.get_height()
plt.text(r1.get_x()+r1.get_width()/2., h1+h2, '%s'% (h1+h2), ha = 'center', va='bottom')

Resources