How To Position Chart in Workbook - python

I am running python2.7, and using openpyxl version 1.8.6. I am able to generate a chart just fine, but am unable to locate anything that indicates the chart can then be positioned in a particular location in a sheet. Any assistance would be appreciated.
I am using the following code to generate the chart:
ws = wb2.get_sheet_by_name('Traffic Data')
rowcount = ws.get_highest_row()
values = Reference(ws,(1,1), (rowcount - 1,1))
labels = Reference(ws,(0,1),(rowcount,0))
title = "Events recorded in " + str(datetime.datetime.strptime(str(runmonth), '%m').strftime('%B'))
series = Series(values, title=title)
chart.add_series(series)
ws = wb2.get_sheet_by_name('Traffic Incidents')
ws.add_chart(chart)

According to the source code it is not possible to set the exact location of the chart while adding it to the worksheet using add_chart().
Consider switching to the xlsxwriter module. Quote from Working with Charts:
# Create a new chart object.
chart = workbook.add_chart({'type': 'line'})
# Add a series to the chart.
chart.add_series({'values': '=Sheet1!$A$1:$A$6'})
# Insert the chart into the worksheet.
worksheet.insert_chart('C1', chart)

I was able to offset the chart position by using chart.drawing. Specifically, I used:
chart.drawing.left = 1000
This offset the chart by about 11 cells. I'm not sure about the pixel to cell mapping, but it can be easily reverse engineered by a few trials.

It's actually really difficult to set the position of any object in Excel because it uses an absurdly stupid system for cell widths: these are based on the width of a number of characters in a particular font and size plus some padding. Charts on the other hand have to be positioned using pixels. We do have the point_pos() method in worksheets but I wouldn't trust it. We've just release 2.0 which has cleaner code. Basically you can play around with the chart.drawing attributes to get it where you need at in what size.
Take look at the code in charts/chart.py for more information. The next release should be a bit more comfortable.

Related

Openpyxl Chart anchor: how to use automated anchor not fixed one?

I'm using this code right now,
which adds a chart into a fix anchor as:
ws.add_chart(chart, "B9")
chart fixed to add at cell B9
However, I'd like to add chart automatically after the max row + 2
because I have multi files with different data rows.
How can I do this?
I couldn't figure it out!

Why am I unable to make a plot containing subplots in plotly using a px.scatter plot?

I have been trying to make a figure using plotly that combines multiple figures together. In order to do this, I have been trying to use the make_subplots function, but I have found it very difficult to have the plots added in such a way that they are properly formatted. I can currently make singular plots (as seen directly below):
However, whenever I try to combine these singular plots using make_subplots, I end up with this:
This figure has the subplots set up completely wrong, since I need each of the four subplots to contain data pertaining to the four methods (A, B, C, and D). In other words, I would like to have four subplots that look like my singular plot example above.
I have set up the code in the following way:
for sequence in sequences:
#process for making sequence profile is done here
sequence_df = pd.DataFrame(sequence_profile)
row_number=1
grand_figure = make_subplots(rows=4, cols=1)
#there are four groups per sequence, so the grand figure should have four subplots in total
for group in sequence_df["group"].unique():
figure_df_group = sequence_df[(sequence_df["group"]==group)]
figure_df_group.sort_values("sample", ascending=True, inplace=True)
figure = px.line(figure_df_group, x = figure_df_group["sample"], y = figure_df_group["intensity"], color= figure_df_group["method"])
figure.update_xaxes(title= "sample")
figure.update_traces(mode='markers+lines')
#note: the next line fails, since data must be extracted from the figure, hence why it is commented out
#grand_figure.append_trace(figure, row = row_number, col=1)
figure.update_layout(title_text="{} Profile Plot".format(sequence))
grand_figure.append_trace(figure.data[0], row = row_number, col=1)
row_number+=1
figure.write_image(os.path.join(output_directory+"{}_profile_plot_subplots_in_{}.jpg".format(sequence, group)))
grand_figure.write_image(os.path.join(output_directory+"grand_figure_{}_profile_plot_subplots.jpg".format(sequence)))
I have tried following directions (like for example, here: ValueError: Invalid element(s) received for the 'data' property) but I was unable to get my figures added as is as subplots. At first it seemed like I needed to use the graph object (go) module in plotly (https://plotly.com/python/subplots/), but I would really like to keep the formatting/design of my current singular plot. I just want the plots to be conglomerated in groups of four. However, when I try to add the subplots like I currently do, I need to use the data property of the figure, which causes the design of my scatter plot to be completely messed up. Any help for how I can ameliorate this problem would be great.
Ok, so I found a solution here. Rather than using the make_subplots function, I just instead exported all the figures onto an .html file (Plotly saving multiple plots into a single html) and then converted it into an image (HTML to IMAGE using Python). This isn't exactly the approach I would have preferred to have, but it does work.
UPDATE
I have found that plotly express offers another solution, as the px.line object has the parameter of facet that allows one to set up multiple subplots within their plot. My code is set up like this, and is different from the code above in that the dataframe does not need to be iterated in a for loop based on its groups:
sequence_df = pd.DataFrame(sequence_profile)
figure = px.line(sequence_df, x = sequence_df["sample"], y = sequence_df["intensity"], color= sequence_df["method"], facet_col= sequence_df["group"])
Although it still needs more formatting, my plot now looks like this, which is works much better for my purposes:

How to have a horizontal scroll bar when a column in the output is really long when using Jupyter and Python

I am trying to use Jupyter + Python. Here is an example of the output
You can see the because the column 'correspondencedata' is too long, so it can not be shown fully in the output.
Can I change this so that a horizontal scroll bar will occur when a column has too long content?
You want to use pd.set_option('max_colwidth', nbr_pixel) before.
If you use a number big enough it will always show the entire content of your cells.
Like, pd.set_option('max_colwidth', 4000)
For more informations:
## To see the actual settings :
pd.get_option("display.max_colwidth")
## To reset with default value
pd.reset_option("max_colwidth")
Documentation

How to set Interval Unit of chart label using openpyxl

I am trying to set Interval Unit (for interval between labels) of chart using openpyxl. This option is set to 'Automatic' by default.
Image shows how we can set the option manually in Excel. Image Link
I found this option in XlsxWriter:
chart.set_x_axis({'interval_unit': 5})
but could not find the option in openpyxl.
Please help.
For bar and column charts in openpyxl the axis labeling individual data is of type openpyxl.chart.axis.TextAxis. TextAxis features a property named tickLblSkip which defines what you are looking for. You can set a labeling interval of 5 as follows:
from openpyxl.chart import BarChart
chart = BarChart
chart.x_axis.tickLblSkip = 5

Python XlsxWriter chart with date axis - cannot set X axis format to date instead of text

I have generated a spreadsheet using XlsxWriter 0.5.3.
The category cells are created using write_datetime() and appear correctly but I have two problems:
1. I want the X axis to be scaled by date instead of my entry so the timescale can be seen.
2. The X axis entries show the number of days instead of a formatted date.
The first can be done by manually changing te X axis format from 'Automatic' or 'Text' to date - is there a way to do it using XlsxWriter or isn't it supported?
The second is a problem because it becomes difficult for someone looking at the chart to go to the correct results. I have tried various solutions and it seems that a cell written using write_timedate() returns the nubmer of days only.
date_time = datetime.datetime.strptime(date_str, '%Y/%m/%d')
worksheet.write_datetime(row_idx, col_idx, date_time, self.formats['Borders date'])
Thanks.
For the first part of your question you can set the 'date_axis': True option in set_x_axis().
See this Date Axis Chart example from the docs.
(source: readthedocs.org)
That should also resolve your second question. If not post a separate question using the above chart example as the sample code.

Categories