How can I use XlsxWriter to plot a barchart and fill in different colors for each of the bar in the same series - xlsxwriter

For example, I have 3 data elements (49, 23, 40 for example) for Jan, Feb and Mar , and they all belong to the same series 1. When I plot them in a bar chart, they can only be filled by the same color in XlsxWriter. What can I do to fill them with different colors? Thanks!

In general in XlsxWriter (and Excel) you can set the colour for a bar chart using the line and/or fill properties.
To set the colour for each bar you need to set the colour for each point in the series. For example:
import xlsxwriter
workbook = xlsxwriter.Workbook('chart.xlsx')
worksheet = workbook.add_worksheet()
worksheet.write_column('A1', ['Jan', 'Feb', 'Mar'])
worksheet.write_column('B1', [49, 23, 40])
chart = workbook.add_chart({'type': 'bar'})
chart.add_series({
'categories': '=Sheet1!$A$1:$A$3',
'values': '=Sheet1!$B$1:$B$3',
'points': [
{'fill': {'color': 'red'}},
{'fill': {'color': 'green'}},
{'fill': {'color': 'blue'}},
],
})
worksheet.insert_chart('B5', chart)
workbook.close()
Output:
See the XlsxWriter documentation on chart series point options and Working with Colors.

Related

coloring histogram with multiple colors where each color has a specified range

I was trying to load an excel data into python and plot it as a histogram. My aim would be to color the histogram according to specific ranges: every number smaller than 4 = yellow, numbers between 4 and 12 = orange and so on. I encountered 2 problems I don´t have 4 separate histograms the programm plots everything in 1 graph. Second problem,one of the loops, obviously is wrong because it only shows everything in yellow.
Could somebody help me out which loop is wrong and why? Is there a better way to do this?I appriciate every help im pretty new at programming.
import matplotlib.pyplot as plt
import pandas as pd
import openpyxl
# Load the workbook
path='C:/Users/akosw/OneDrive/Desktop/Programmieren/Geotechnikstammdaten.xlsx'
#workbook = openpyxl.load_workbook("Geotechnikstammdaten.xlsx","C:/Users/akosw/OneDrive/Desktop/Programmieren")
workbook = openpyxl.load_workbook(path)
# Select the sheet
sheet = workbook['Tabelle3']
# Extract the values from each column
columns = [[cell.value for cell in column] for column in zip(*sheet.rows)]
# Iterate over the columns
for i, values in enumerate(columns):
# Create the histogram
plt.hist(values, bins=50)
# Color the bars according to the specified rules
for patch in plt.gca().patches:
if patch.get_height() < 4:
patch.set_facecolor('yellow')
elif patch.get_height() < 12:
patch.set_facecolor('orange')
elif patch.get_height() < 26:
patch.set_facecolor('green')
elif patch.get_height() < 51:
patch.set_facecolor('blue')
else:
patch.set_facecolor('red')
plt.title(f'Column {i+1}')
plt.show()
# Save the histogram to a file
# plt.savefig(f'histogram_{i+1}.png')
Here is kind of what im trying to achiev but instead of a bar chart i want a histogramm.
from bisect import bisect
import matplotlib.pyplot as plt
import numpy as np
OM_VALUES = [4, 12, 26, 51]
OM_COLORS = ["yellow", "orange", "blue", "green", "red"]
data = [4, 6, 7, 7, 11, 16, 23, 30, 30, 27, 1, 3, 4, 33, 37, 39, 45, 51]
labels = range(len(data))#[0,1,2,3,4,5,6,7,8,9,10,11]
plt.barh(labels, data,height=1.0, color=[OENORM_COLORS[bisect(OENORM_VALUES, v)] for v in data])
plt.title('Counts per depth')
plt.xlabel('Value')
plt.ylabel('Depth')
#plt.savefig('counts_depth.png')
plt.show()

Highlighting a portion of a line chart in excel

I have this reproducible example below where I create a random dataframe then plot it on excel using xlsxwriter:
import pandas as pd
import numpy as np
import xlsxwriter
import random
df = pd.DataFrame({"Start": pd.date_range("1-jan-2021", periods=72, freq="1H"),
'Cases': np.random.randint(0,100,size=(72))})
dates_tohighlight = list(pd.date_range("2-jan-2021", periods=10, freq="1H"))
highlighted_rows = df['Start'].isin(dates_tohighlight).map({True: 'background-color: green', False: 'background-color: grey'})
styler = df.style.apply(lambda _: highlighted_rows).set_properties(**{'text-align': 'center'})
writer = pd.ExcelWriter("Output2.xlsx", engine='xlsxwriter') # pylint: disable=abstract-class-instantiated
styler.to_excel(writer, sheet_name= 'Keyser', startrow= start_row , startcol=0, index=False)
workbook = writer.book # pylint: disable=E1101
worksheet = writer.sheets['Keyser']
(max_rows, max_cols) = df.shape
start_row = 3
chart = workbook.add_chart({'type': 'line'})
chart.add_series({
'name' : 'Test Graph',
'values': f'=Keyser!$B${start_row}:$B${max_rows+start_row}',
'categories': f'=Keyser!$A${start_row}:$A${max_rows+start_row}'})
chart.set_x_axis({'name': 'Timesteps', 'position_axis': 'on_tick', 'text_axis':True, 'num_font': {'rotation': -45}})
chart.set_y_axis({'name': 'Random numbers', 'major_gridlines': {'visible': False}})
worksheet.insert_chart('D3', chart, {'x_scale': 1.5, 'y_scale': 1.5})
writer.save()
I want to either draw two vertical lines as boundaries on the graphic to show the studied zone or highlight that portion's background on the graphic (I'm talking about the 'dates_tohighlight' portion). Thank you !
Edit:
Do you think I should abandon this method & use matplotlib instead then export the image to excel (since it's possible to highlight a portion of a graph in that module ) ?

bi-directional bar chart with annotation in python plotly

I have a pandas dataset with a toy version that can be created with this
#creating a toy pandas dataframe
s1 = pd.Series(['dont have a mortgage',-31.8,'have mortgage',15.65])
s2 = pd.Series(['have utility bill arrears',-21.45,'',0])
s3 = pd.Series(['have interest only mortgage',-19.59,'',0])
s4 = pd.Series(['bank with challenger bank',-19.24,'bank with a traditional bank',32.71])
df = pd.DataFrame([list(s1),list(s2),list(s3),list(s4)], columns = ['label1','value1','label2','value2'])
I want to create a bar chart that looks like this version I hacked together in excel
I want to be able to supply RGB values to customise the two colours for the left and right bars (currently blue and orange)
I tried different versions using “fig.add_trace(go.Bar” but am brand new to plotly and cant get anything to work with different coloured bars on one row with annotation under each bar.
All help greatly appreciated!
thanks
To create a double-sided bar chart, you can create two subplots with shared x- and y-axis. Each subplot is a horizontal bar chart with a specified marker color
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# define data set
s1 = pd.Series(['dont have a mortgage',-31.8,'have mortgage',15.65])
s2 = pd.Series(['have utility bill arrears',-21.45,'',0])
s3 = pd.Series(['have interest only mortgage',-19.59,'',0])
s4 = pd.Series(['bank with challenger bank',-19.24,'bank with a traditional bank',32.71])
df = pd.DataFrame([list(s1),list(s2),list(s3),list(s4)], columns = ['label1','value1','label2','value2'])
# create subplots
fig = make_subplots(rows=1, cols=2, specs=[[{}, {}]], shared_xaxes=True,
shared_yaxes=True, horizontal_spacing=0)
fig.append_trace(go.Bar(y=df.index, x=df.value1, orientation='h', width=0.4, showlegend=False, marker_color='#4472c4'), 1, 1)
fig.append_trace(go.Bar(y=df.index, x=df.value2, orientation='h', width=0.4, showlegend=False, marker_color='#ed7d31'), 1, 2)
fig.update_yaxes(showticklabels=False) # hide all yticks
The annotations need to be added separately:
annotations = []
for i, row in df.iterrows():
if row.label1 != '':
annotations.append({
'xref': 'x1',
'yref': 'y1',
'y': i,
'x': row.value1,
'text': row.value1,
'xanchor': 'right',
'showarrow': False})
annotations.append({
'xref': 'x1',
'yref': 'y1',
'y': i-0.3,
'x': -1,
'text': row.label1,
'xanchor': 'right',
'showarrow': False})
if row.label2 != '':
annotations.append({
'xref': 'x2',
'yref': 'y2',
'y': i,
'x': row.value2,
'text': row.value2,
'xanchor': 'left',
'showarrow': False})
annotations.append({
'xref': 'x2',
'yref': 'y2',
'y': i-0.3,
'x': 1,
'text': row.label2,
'xanchor': 'left',
'showarrow': False})
fig.update_layout(annotations=annotations)
fig.show()

xlsxwriter: modifying parts of a line in a scatter chart

in the Python package xlsxwriter, is it possible to format a part of a scatter chart series differently than another part? for example, a scatter chart where some sections of the line of a specific series are blue, and other sections of the same line are red. it is certainly possible in Excel itself by modifying specific data points.
I tried using the 'points' option in many combinations without success. I don't know which options are valid for it in a scatter chart.
UPDATE:
here is an example of what I'm trying to achieve. This was created directly in Excel, not through xlsxwriter. Notice how one section of the line is dashed and red, and another is a different thickness. To create it, simply select a data point and use the options in the sidebar to adjust formatting.
I've made an example that I think answers your question.
I'm using Python 3.5 and xlsxwriter 0.9.6.
In chart 1, I changed the color of the markers based on whether they were in a particular group. It's fairly straightforward if chart 1 is what you're looking for.
In chart 2, I show how to hard code a continuous line with different colors (there may be a better way to do this).
import xlsxwriter
import numpy as np
import pandas as pd
dates = pd.DataFrame({'excel_date':pd.date_range('1/1/2016', periods=12, freq='M')})
dates.excel_date = dates.excel_date - pd.datetime(1899, 12, 31)
data = np.array([11,20,25,35,40,48,44,31,25,38,49,60])
selection = np.array([4,5,6,8,11])
#Creating a list - you could hard code these lines if you prefer depending on the size of your series
diff_color_list = list()
for n in range(1, 13):
if n in selection:
diff_color_list.append({'fill':{'color': 'blue', 'width': 3.25}},)
else:
diff_color_list.append({'fill':{'color': 'red', 'width': 3.25}},)
#Workbook Creation
workbook = xlsxwriter.Workbook("test.xlsx")
format = workbook.add_format({'num_format':'mmm-yy'})
worksheet1 = workbook.add_worksheet("testsheet")
worksheet1.write('A1', 'Date')
worksheet1.write('B1', 'Data')
worksheet1.write_column('A2', dates.excel_date, format)
worksheet1.write_column('B2', data)
chart1 = workbook.add_chart({'type': 'scatter'})
# Configure the series.
chart1.add_series({'categories': '=testsheet!$A$2:$A$13',
'values': '=testsheet!$B$2:$B$13',
'points': diff_color_list
})
chart1.set_title ({'name': 'Results'})
chart1.set_x_axis({'name': 'Date'})
chart1.set_y_axis({'name': 'Data'})
chart1.set_legend({'none': True})
# Second chart with alternating line colors
chart2 = workbook.add_chart({'type': 'scatter',
'subtype': 'straight'})
chart2.add_series({'categories': '=testsheet!$A$2:$A$3',
'values': '=testsheet!$B$2:$B$3',
'line':{'color': 'blue'}
})
chart2.add_series({'categories': '=testsheet!$A$3:$A$4',
'values': '=testsheet!$B$3:$B$4',
'line':{'color': 'red'}
})
chart2.add_series({'categories': '=testsheet!$A$4:$A$5',
'values': '=testsheet!$B$4:$B$5',
'line':{'color': 'blue'}
})
chart2.set_title ({'name': 'Results'})
chart2.set_x_axis({'name': 'Date'})
chart2.set_y_axis({'name': 'Data'})
chart2.set_legend({'none': True})
worksheet1.insert_chart('D6', chart1)
worksheet1.insert_chart('L6', chart2)
workbook.close()
The question is a little bit confusing since you talk about changing the color of parts of a line but also about points.
I'm going to assume you are referring to changing the color of points/markers since as far as I know changing the color of line segments in a series isn't possible in Excel.
Anyway, it it possible to change marker colors in a scatter chart using XlsxWriter. For example:
import xlsxwriter
workbook = xlsxwriter.Workbook('chart_scatter.xlsx')
worksheet = workbook.add_worksheet()
# Add the worksheet data that the charts will refer to.
worksheet.write_column('A1', [1, 2, 3, 4, 5, 6])
worksheet.write_column('B1', [15, 40, 50, 20, 10, 50])
# Create a new scatter chart.
chart = workbook.add_chart({'type': 'scatter',
'subtype': 'straight_with_markers'})
# Configure the chart series. Increase the default marker size for clarity
# and configure the series points to
chart.add_series({
'categories': '=Sheet1!$A$1:$A$6',
'values': '=Sheet1!$B$1:$B$6',
'marker': {'type': 'square',
'size': 12},
'points': [
None,
None,
{'fill': {'color': 'green'},
'border': {'color': 'black'}},
None,
{'fill': {'color': 'red'},
'border': {'color': 'black'}},
],
})
# Turn off the legend for clarity.
chart.set_legend({'none': True})
# Insert the chart into the worksheet.
worksheet.insert_chart('D2', chart)
workbook.close()
Output:

xlsxwriter can not make the chart wider

I have create a chart by calling
worksheet.insert_chart(chart_row, chart, {'x_scale': 2, 'y_scale': 1})
it is a stacked type.
I want to make the chart horizontal wider, I tried to change x_scale to a big value, it does not do anything to the chart. when I changed it to 0.5, the chart does shrink. it looks like 1, 2, 3,4 value do not make any impact the chart.
Any ideas?
Thanks
It should work. Here is an example:
import xlsxwriter
workbook = xlsxwriter.Workbook('chart.xlsx')
worksheet = workbook.add_worksheet()
chart1 = workbook.add_chart({'type': 'column'})
chart2 = workbook.add_chart({'type': 'column'})
data = [2, 4, 6, 8, 4]
worksheet.write_column('A1', data)
chart1.add_series({'values': '=Sheet1!$A$1:$A$5'})
chart2.add_series({'values': '=Sheet1!$A$1:$A$5'})
worksheet.insert_chart('C1', chart1)
worksheet.insert_chart('C16', chart2, {'x_scale': 2, 'y_scale': 1})
workbook.close()
And here is the output: