Multiple Lables on X-Axis in Plotly Python - python-3.x

I need to create a bar chart with time series values on the x-axis but they should be in layers, the example of the graph below.[![desired version][1]][1]
Right now I managed to get this for now: [![my version][2]][2]
[1]: https://i.stack.imgur.com/PQnc5.png
[2]: https://i.stack.imgur.com/1Z1aC.png
The code for the graph is here:
#creating traces for the bar chart trace_desks_popl = go.Bar(
x=df_estate_desks['Time Slot'],
y=df_estate_desks['Occupancy x Hour'],
name='Desks',
marker_color = '#26A2ED'
)
trace_meeting_popl = go.Bar(
x=df_estate_meet['Time Slot'],
y=df_estate_meet['Population x Hour'],
name='Meeting Rooms, Offices & Breakout Spaces',
marker_color = '#41C572'
)
#creating the stack bar chart data_estate_popl=[trace_desks_popl, trace_meeting_popl] layout_estate_popl= go.Layout(
barmode= 'stack',
title='Total Estate Population',
xaxis=dict(title='Time'),
yaxis=dict(title='Number of People'),
template="simple_white",
height = 700,
width=1000,
bargap=0.03
) fig_estate_popl= go.Figure(data=data_estate_popl, layout=layout_estate_popl)
#adding the line for average population avg_estate_popl = round((df_estate_meet['Population x Hour'] + df_estate_desks['Occupancy x Hour']).mean()) fig_estate_popl.layout.xaxis2 = go.layout.XAxis(overlaying='x', range=[0, 2], showticklabels=False) fig_estate_popl.add_scatter(x = [0, 2], y = [avg_estate_popl, avg_estate_popl], mode= 'lines+text', xaxis='x2', line_dash ='dot', marker_color = 'Grey',
text='Avg: ' + str(avg_estate_popl),
textposition='top left',
textfont=dict(color='Black'),
name='citations',
showlegend=False)
#adding the line for minimum population min_estate_popl = round((df_estate_meet['Population x Hour'] + df_estate_desks['Occupancy x Hour']).min()) fig_estate_popl.add_scatter(x = [0, 2], y = [min_estate_popl, min_estate_popl], mode= 'lines+text', xaxis='x2', line_dash ='dot', marker_color = 'Grey',
text='Min: ' + str(min_estate_popl),
textposition='top left',
textfont=dict(color='Black'),
name='citations',
showlegend=False)
#adding the line for maximum population max_estate_popl = round((df_estate_meet['Population x Hour'] + df_estate_desks['Occupancy x Hour']).max()) fig_estate_popl.add_scatter(x = [0, 2], y = [max_estate_popl, max_estate_popl], mode= 'lines+text', xaxis='x2', line_dash ='dot', marker_color = 'Grey',
text='Max: ' + str(max_estate_popl),
textposition='top left',
textfont=dict(color='Black'),
name='citations',
showlegend=False)
fig_estate_popl.show()
I can add the dictionary of the dataframes I used if needed. Thank you!

Related

Plotly Custom Legend

I have a plotly plot which looks like this:
The Code I am using is below:
fig = make_subplots(specs=[[{"secondary_y": True}]])
fig.add_trace(go.Scatter( x = pf['Timestamp'], y = pf['Price_A'], name ='<b>A</b>',
mode = 'lines+markers',
marker_color = 'rgba(255, 0, 0, 0.8)',
line = dict(width = 3 ), yaxis = "y1"),
secondary_y=False,)
fig.add_trace(go.Scatter( x = df['Timestamp'], y = df['Price_B'], name='<b>B</b>',
mode = 'lines+markers',
marker_color = 'rgba(0, 196, 128, 0.8)',
line = dict(width = 3 ), yaxis = "y1") ,
secondary_y=False,)
for i in pf2['Timestamp']:
fig.add_vline(x=i, line_width=3, line_dash="dash", line_color="purple",
name='Event')
fig.update_layout( title="<b>Change over Time</b>", font=dict( family="Courier New,
monospace", size=16, color="RebeccaPurple"),
legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01
))
How can I add the entry in the legend for the event that is denoted by the vertical lines?
When you use add_vline, you are adding an annotation which will not have a corresponding legend entry.
You'll need to instead use go.Scatter to plot the vertical lines, passing the minimum and maximum values in your data (plus or minus some padding) to the y parameter. Then you can set this same y-range for your plot. This will give you the appearance of vertical lines while still showing the full range of your data.
Update: you can use a legend group so that the vertical lines appear as a single entry in the legend
For example:
from pkg_resources import yield_lines
import plotly.express as px
import plotly.graph_objects as go
fig = go.Figure()
df = px.data.stocks()
for col in ['GOOG','AMZN']:
fig.add_trace(go.Scatter(
x=df['date'],
y=df[col]
))
vlines = ["2018-07-01","2019-04-01","2019-07-01"]
min_y,max_y = df[['GOOG','AMZN']].min().min(), df[['GOOG','AMZN']].max().max()
padding = 0.05*(max_y-min_y)
for i,x in enumerate(vlines):
fig.add_trace(go.Scatter(
x=[x]*2,
y=[min_y-padding, max_y+padding],
mode='lines',
line=dict(color='purple', dash="dash"),
name="vertical lines",
legendgroup="vertical lines",
showlegend=True if i == 0 else False
))
fig.update_yaxes(range=[min_y-padding, max_y+padding])
fig.show()

Equal spacing between pie charts of different sizes in matplotlib

I am having difficulties with setting an equal space between pie charts of different sizes. The 5 are correctly arranged in one row, but the distance between the contours of neighboring pies aren't equal. I tried many abbreviations of the following code, all of them not making a big difference in the output (see image):
#code:
import matplotlib.pyplot as plt
import pandas as pd
labels = 'Verkehr', 'Maschinen und Motoren', 'Feuerungen', 'Industrie / Gewerbe', 'Land- und Forstwirtschaft'
sizesax1 = [108295, 10107, 7220, 11551, 7220]
sizesax2 = [77882, 6676, 6676, 13351, 6676]
sizesax3 = [55652, 4417, 6184, 15900, 6184]
sizesax4 = [36327, 2642, 4632, 16512, 5944]
sizesax5 = [18781, 1409, 3287, 1878, 4695]
fig, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(1, 5, figsize =(20,4))
ax1.pie(sizesax1, startangle=0, colors = ('red', 'darkblue', 'orange', 'yellow', 'green'), radius=1*4)
ax2.pie(sizesax2, startangle=0, colors = ('red', 'darkblue', 'orange', 'yellow', 'green'), radius=.77*4)
ax3.pie(sizesax3, startangle=0, colors = ('red', 'darkblue', 'orange', 'yellow', 'green'), radius=.61*4)
ax4.pie(sizesax4, startangle=0, colors = ('red', 'darkblue', 'orange', 'yellow', 'green'), radius=.46*4)
ax5.pie(sizesax5, startangle=0, colors = ('red', 'darkblue', 'orange', 'yellow', 'green'), radius=.33*4)
some additions i tried:
fig.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=1, hspace=None)
or
fig.tight_layout()
#giving me this error message:
/srv/conda/envs/notebook/lib/python3.7/site-packages/ipykernel_launcher.py:17: UserWarning:
Tight layout not applied. The bottom and top margins cannot be made large enough to
accommodate all axes decorations.
and some others.
Big thank you already for reading this! I am a complete beginner in python and just managed to come as far as you see in this image:
enter image description here
It is not clear what it is required. I'll assume it is the following image:
Fundamentally, the problem is that the pie needs a square aspect ratio, which is not provided by a row of subplots.
The simplest solution, is to create only one plot and plot there multiple pies with different centres. Something like:
import matplotlib.pyplot as plt
sizes = [ [108295, 10107, 7220, 11551, 7220],
[77882, 6676, 6676, 13351, 6676],
[55652, 4417, 6184, 15900, 6184],
[36327, 2642, 4632, 16512, 5944],
[18781, 1409, 3287, 1878, 4695]]
colors = ('red', 'darkblue', 'orange', 'yellow', 'green')
R = 4
radius = [R*i for i in [1.0, 0.77, 0.61, 0.46, 0.33] ]
wid = sum(radius)*2
hei = R*2
fig, ax = plt.subplots(figsize =(wid,hei))
fig.subplots_adjust(left = 0, right = 1, bottom = 0, top = 1)
y = R
x = 0
for i in range(5):
x += radius[i]
ax.pie(sizes[i], startangle = 0, colors = colors,
radius = radius[i], center = (x,y) )
x += radius[i]
ax.set(xlim =(0,x), ylim=(0,R*2))
plt.savefig("aaa.png")
Notice that my figure aspect ratio is not the (20,4) of the question, which does not hold for the way I interpreted the intended result.
But it might be the case that there is the need of having these in different axes. If so, the idea is:
Use gridspec to create a single row with 5 columns and provide the ratios so that they correspond to the required radius.
Plot the larger pie in the left slot.
In all remaining slots, use a subgrid, dividing into a column of three (sub-)slots.
Set the height ratios so that the middle one ends up with an aspect ratio of a square.
Plot the pies in the middle slots.
Here we go:
import matplotlib.pyplot as plt
sizes = [ [108295, 10107, 7220, 11551, 7220],
[77882, 6676, 6676, 13351, 6676],
[55652, 4417, 6184, 15900, 6184],
[36327, 2642, 4632, 16512, 5944],
[18781, 1409, 3287, 1878, 4695]]
colors = ('red', 'darkblue', 'orange', 'yellow', 'green')
R = 4
radius = [R*i for i in [1.0, 0.77, 0.61, 0.46, 0.33] ]
wid = sum(radius)*2
hei = R*2
ratios = [i/radius[0] for i in radius] # for gridspec
fig = plt.figure(figsize =(wid,hei))
gs = fig.add_gridspec(1, 5,
width_ratios = ratios,
wspace=0, left = 0, right = 1, bottom = 0, top = 1)
ax = fig.add_subplot(gs[0,0])
ax.pie(sizes[0], startangle = 0, colors = colors, radius = 1 )
ax.set(xlim=(-1,1) ,ylim=(-1,1))
for i in range(1,5):
mid = ratios[i]/sum(ratios)*wid
inrat = [(hei-mid)/2, mid, (hei-mid)/2]
ings = gs[0,i].subgridspec(3, 1, hspace=0,
height_ratios = inrat)
ax = fig.add_subplot(ings[1,0])
ax.pie(sizes[i], startangle = 0, colors = colors, radius = 1 )
ax.set(xlim=(-1,1), ylim=(-1,1))
plt.savefig("aaa.png")

How to combine two x axes using subplot

I have two plots (candle and bar). I want to combine them in the same subplot (x-axes in the top for volume and x-axes at the bottom for dates), but when I try to combine both in the same subplot (row=2, col=1), the result it's not the expected.
import plotly from plotly
import subplots
import random
import pandas as pd
import plotly.graph_objects as go
fig = make_subplots(rows=3, cols=2)
high = 40
low = 5
dev = 1
days = 18
fake_market = []
for each in range(days):
ohlc = []
ohlc.append(each)
if each == 0:
o = random.randrange(low, high)
ohlc.append(o)
else:
ohlc.append(c) #I know
h = random.randrange(o, high)
ohlc.append(h)
l = random.randrange(low, o)
ohlc.append(l)
c = random.randrange(l, h)
ohlc.append(c)
fake_market.append(ohlc)
fake_volume = [[x, random.randrange(1, 200)] for x in range(low, (high+1))]
df = pd.DataFrame(fake_market, columns=["Date", "Open", "High", "Low", "Close"])
df2 = pd.DataFrame(fake_volume, columns=["Volume", "Price"])
fecha = ['2019-03-22', '2019-03-23', '2019-03-24', '2019-03-25',
'2019-03-26', '2019-03-27', '2019-03-28', '2019-03-29',
'2019-03-30', '2019-03-31', '2019-04-01', '2019-04-02',
'2019-04-03', '2019-04-04', '2019-04-05', '2019-04-06',
'2019-04-07', '2019-04-08']
candle =go.Candlestick(
x=fecha,
open=[str(x) for x in df.Open.to_list()],
high=[str(x) for x in df.High.to_list()],
low=[str(x) for x in df.Low.to_list()],
close=[str(x) for x in df.Close.to_list()],
visible=True,
showlegend=True,
xaxis='x3',
yaxis ='y3')
vol_bar = go.Bar(
x=[str(x) for x in df2.Price.to_list()],
y=[str(x) for x in df2.Volume.to_list()],
xaxis='x4',
yaxis ='y4',
name='volume',
orientation="h",
opacity=0.4, marker=dict(
color='rgba(246, 78, 139, 0.6)', line=dict(color='rgba(246, 78, 139, 1.0)', width=0.1)))
fig.add_trace(candle, row=2, col=1)
fig.add_trace(vol_bar, row=2, col=1)
fig.update_layout(
yaxis3=dict(
title="yaxis3 title",
titlefont=dict(
color="#1f77b4"
),
tickfont=dict(
color="#1f77b4"
)
),
yaxis4=dict(
title="yaxis4 title", side='right',
titlefont=dict(
color="#1f77b4"
),
tickfont=dict(
color="#1f77b4"
)
),
xaxis3=dict(
title="xaxis3 volume", side='top', overlaying='x',
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
)),
xaxis4=dict(
title="xaxis4 date", side='bottom',
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
))
)
fig.update_xaxes(rangeslider_visible=False)
fig.show()
The plots are showed as follow:
The plots:
The result: The result:
The plot expected: The plot expected:
Apparently the x axes are mixing and that is the reason for getting a distorted graph is obtained.

How can I use the plotly dropdown menu feature to update the z value in my choropleth map?

I just want to create a menu on the plot where I'm able to change the z-value in data only. I tried looking at other examples on here: https://plot.ly/python/dropdowns/#restyle-dropdown but it was hard since the examples were not exactly similar to my plot.
import plotly
import plotly.plotly as py
import plotly.graph_objs as go
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv')
data = [go.Choropleth(
locations = df['CODE'],
z = df['GDP (BILLIONS)'],
text = df['COUNTRY'],
colorscale = [
[0, "rgb(5, 10, 172)"],
[0.35, "rgb(40, 60, 190)"],
[0.5, "rgb(70, 100, 245)"],
[0.6, "rgb(90, 120, 245)"],
[0.7, "rgb(106, 137, 247)"],
[1, "rgb(220, 220, 220)"]
],
autocolorscale = False,
reversescale = True,
marker = go.choropleth.Marker(
line = go.choropleth.marker.Line(
color = 'rgb(180,180,180)',
width = 0.5
)),
colorbar = go.choropleth.ColorBar(
tickprefix = '$',
title = 'GDP<br>Billions US$'),
)]
layout = go.Layout(
title = go.layout.Title(
text = '2014 Global GDP'
),
geo = go.layout.Geo(
showframe = False,
showcoastlines = False,
projection = go.layout.geo.Projection(
type = 'equirectangular'
)
),
annotations = [go.layout.Annotation(
x = 0.55,
y = 0.1,
xref = 'paper',
yref = 'paper',
text = 'Source: <a href="https://www.cia.gov/library/publications/the-world-factbook/fields/2195.html">\
CIA World Factbook</a>',
showarrow = False
)]
)
fig = go.Figure(data = data, layout = layout)
py.iplot(fig, filename = 'd3-world-map')
It's been a while since this was asked, but I figured it was still worth answering. I can't speak to how this might have changed since it was asked in 2019, but this works today.
First, I'll provide the code I used to create the new z values and the dropdown menu, then I'll provide all of the code I used to create these graphs in one chunk (easier to cut and paste...and all that).
This is the data I used for the alternate data in the z field.
import plotly.graph_objects as go
import pandas as pd
import random
z2 = df['GDP (BILLIONS)'] * .667 + 12
random.seed(21)
random.shuffle(z2)
df['z2'] = z2 # example as another column in df
print(df.head()) # validate as expected
z3 = df['GDP (BILLIONS)'] * .2 + 1000
random.seed(231)
random.shuffle(z3) # example as a series outside of df
z4 = df['GDP (BILLIONS)']**(1/3) * df['GDP (BILLIONS)']**(1/2)
random.seed(23)
random.shuffle(z4)
z4 = z4.tolist() # example as a basic Python list
To add buttons to change z, you'll add updatemenus to your layout. Each dict() is a separate dropdown option. At a minimum, each button requires a method, a label, and args. These represent what is changing (method for data, layout, or both), what it's called in the dropdown (label), and the new information (the new z in this example).
args for changes to data (where the method is either restyle or update) can also include the trace the change applies to. So if you had a bar chart and a line graph together, you may have a button that only changes the bar graph.
Using the same structure you have:
updatemenus = [go.layout.Updatemenu(
x = 1, xanchor = 'right', y = 1.15, type = "dropdown",
pad = {'t': 5, 'r': 20, 'b': 5, 'l': 30}, # around all buttons (not indiv buttons)
buttons = list([
dict(
args = [{'z': [df['GDP (BILLIONS)']]}], # original data; nest data in []
label = 'Return to the Original z',
method = 'restyle' # restyle is for trace updates
),
dict(
args = [{'z': [df['z2']]}], # nest data in []
label = 'A different z',
method = 'restyle'
),
dict(
args = [{'z': [z3]}], # nest data in []
label = 'How about this z?',
method = 'restyle'
),
dict(
args = [{'z': [z4]}], # nest data in []
label = 'Last option for z',
method = 'restyle'
)])
)]
All code used to create this graph in one chunk (includes code shown above).
import plotly.graph_objs as go
import pandas as pd
import ssl
import random
# to collect data without an error
ssl._create_default_https_context = ssl._create_unverified_context
# data used in plot
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv')
# z values used in buttons
z2 = df['GDP (BILLIONS)'] * .667 + 12
random.seed(21)
random.shuffle(z2)
df['z2'] = z2 # example as another column in the data frame
print(df.head()) # validate as expected
z3 = df['GDP (BILLIONS)'] * .2 + 1000
random.seed(231)
random.shuffle(z3) # example as a series outside of the data frame
z4 = df['GDP (BILLIONS)']**(1/3) * df['GDP (BILLIONS)']**(1/2)
random.seed(23)
random.shuffle(z4)
z4 = z4.tolist() # example as a basic Python list
data = [go.Choropleth(
locations = df['CODE'], z = df['GDP (BILLIONS)'], text = df['COUNTRY'],
colorscale = [
[0, "rgb(5, 10, 172)"],
[0.35, "rgb(40, 60, 190)"],
[0.5, "rgb(70, 100, 245)"],
[0.6, "rgb(90, 120, 245)"],
[0.7, "rgb(106, 137, 247)"],
[1, "rgb(220, 220, 220)"]],
reversescale = True,
marker = go.choropleth.Marker(
line = go.choropleth.marker.Line(
color = 'rgb(180,180,180)', width = 0.5)),
colorbar = go.choropleth.ColorBar(
tickprefix = '$',
title = 'GDP<br>Billions US$',
len = .6) # I added this for aesthetics
)]
layout = go.Layout(
title = go.layout.Title(text = '2014 Global GDP'),
geo = go.layout.Geo(
showframe = False, showcoastlines = False,
projection = go.layout.geo.Projection(
type = 'equirectangular')
),
annotations = [go.layout.Annotation(
x = 0.55, y = 0.1, xref = 'paper', yref = 'paper',
text = 'Source: <a href="https://www.cia.gov/library/publications/the-world-factbook/fields/2195.html">\
CIA World Factbook</a>',
showarrow = False
)],
updatemenus = [go.layout.Updatemenu(
x = 1, xanchor = 'right', y = 1.15, type = "dropdown",
pad = {'t': 5, 'r': 20, 'b': 5, 'l': 30},
buttons = list([
dict(
args = [{'z': [df['GDP (BILLIONS)']]}], # original data; nest data in []
label = 'Return to the Original z',
method = 'restyle' # restyle is for trace updates only
),
dict(
args = [{'z': [df['z2']]}], # nest data in []
label = 'A different z',
method = 'restyle'
),
dict(
args = [{'z': [z3]}], # nest data in []
label = 'How about this z?',
method = 'restyle'
),
dict(
args = [{'z': [z4]}], # nest data in []
label = 'Last option for z',
method = 'restyle'
)])
)]
)
fig = go.Figure(data = data, layout = layout)
fig.show()

Plotting Points in Basemap python

I want to plot the map of a ship data. I am using the following code:
with open ('Data.txt', 'r',encoding = 'utf-8') as f:
d = json.load(f)
# create a dataFrame
df = pd.DataFrame(([dict(id=data['id'],
X = data['x'],
Y = data['y'],
)
for data in d['features']]))
lat = df['X'].values
lon = df['Y'].values
margin = 1 # create a margin for the maps
lat_min = min(lat) - margin
lat_max = max(lat) + margin
lon_min = min(lon) - margin
lon_max = max(lon) + margin
# create a map
m = Basemap(llcrnrlon= lon_min,
llcrnrlat= lat_min,
urcrnrlon = lon_max,
urcrnrlat= lat_max,
lat_0= (lat_max - lat_min) / 2,
lon_0= (lon_max - lon_min) / 2,
projection= 'merc',
resolution= 'h',
area_thresh= 10,
)
m.drawcoastlines() # draw a coastlines
m.drawcounties(zorder=20) # draw a countries map in graph
m.drawstates()
m.drawmapboundary(fill_color= '#46bcec')
m.fillcontinents(color= 'white', lake_color= '#85A6D9')
lons, lats = m(lon, lat)
m.scatter(lons, lats, marker = 'o', zorder= 5, s= 5, c= 'g', )
plt.title('Give a proper title')
plt.show()
But while I run the code, it gives me following error:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 2: invalid continuation byte in the following line:
m.drawcounties(zorder=20)
I dont know how to fix it.

Resources