I'm plotting some data similar to the first example found here (the US airports map). However, rather than plotting a scale I'm plotting binary features (let's say one color is over 15k flights and one color is under 15k flights). I've looked at the documentation but can't find a way to do a legend if I wanted to do this sort of plot. Does anyone know how?
You could specify the color according to your condition, e.g.
color = np.where(df['Set'] > 15000, 'red', 'green')
but then you wouldn't have a nice legend.
An alternative approach would be to add two plots, one for each condition.
import pandas as pd
import plotly
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2011_february_us_airport_traffic.csv')
data = dict(
type = 'scattergeo',
locationmode = 'USA-states',
mode = 'markers'
)
data_high = data.copy()
data_high['lon'] = df[df['cnt'] > 10000 ]['long']
data_high['lat'] = df[df['cnt'] > 10000 ]['lat']
data_high['marker'] = dict(color = 'red')
data_high['name'] = '> 10000'
data_low = data.copy()
data_low['lon'] = df[df['cnt'] <= 10000 ]['long']
data_low['lat'] = df[df['cnt'] <= 10000 ]['lat']
data_low['marker'] = dict(color = 'green')
data_low['name'] = '<= 10000'
layout = dict(
geo = dict(
scope = 'usa',
projection = dict(type='albers usa'),
),
)
fig = dict(data=[data_high, data_low], layout=layout)
plotly.offline.plot(fig)
Related
This question already has answers here:
Plotly: How to make a figure with multiple lines and shaded area for standard deviations?
(4 answers)
Closed 1 year ago.
I need to plot data with continuous error bands. I would like to use Plotly Express in the same way as plotly.express.scatter, but instead of error bars to get continuous error bands. With "continuous error bands" I am talking about this:
I wrote the following function to extend plotly.express.line with the same high level interface of Plotly Express. In case it is useful to other people, this is the function:
import plotly.express as px
import plotly.graph_objs as go
def line(error_y_mode=None, **kwargs):
"""Extension of `plotly.express.line` to use error bands."""
ERROR_MODES = {'bar','band','bars','bands',None}
if error_y_mode not in ERROR_MODES:
raise ValueError(f"'error_y_mode' must be one of {ERROR_MODES}, received {repr(error_y_mode)}.")
if error_y_mode in {'bar','bars',None}:
fig = px.line(**kwargs)
elif error_y_mode in {'band','bands'}:
if 'error_y' not in kwargs:
raise ValueError(f"If you provide argument 'error_y_mode' you must also provide 'error_y'.")
figure_with_error_bars = px.line(**kwargs)
fig = px.line(**{arg: val for arg,val in kwargs.items() if arg != 'error_y'})
for data in figure_with_error_bars.data:
x = list(data['x'])
y_upper = list(data['y'] + data['error_y']['array'])
y_lower = list(data['y'] - data['error_y']['array'] if data['error_y']['arrayminus'] is None else data['y'] - data['error_y']['arrayminus'])
color = f"rgba({tuple(int(data['line']['color'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4))},.3)".replace('((','(').replace('),',',').replace(' ','')
fig.add_trace(
go.Scatter(
x = x+x[::-1],
y = y_upper+y_lower[::-1],
fill = 'toself',
fillcolor = color,
line = dict(
color = 'rgba(255,255,255,0)'
),
hoverinfo = "skip",
showlegend = False,
legendgroup = data['legendgroup'],
xaxis = data['xaxis'],
yaxis = data['yaxis'],
)
)
# Reorder data as said here: https://stackoverflow.com/a/66854398/8849755
reordered_data = []
for i in range(int(len(fig.data)/2)):
reordered_data.append(fig.data[i+int(len(fig.data)/2)])
reordered_data.append(fig.data[i])
fig.data = tuple(reordered_data)
return fig
and this is an usage example:
import plotly.express as px
import pandas
df = px.data.gapminder().query('continent=="Americas"')
df = df[df['country'].isin({'Argentina','Brazil','Colombia'})]
df['lifeExp std'] = df['lifeExp']*.1 # Invent some error data...
for error_y_mode in {'band', 'bar'}:
fig = line(
data_frame = df,
x = 'year',
y = 'lifeExp',
error_y = 'lifeExp std',
error_y_mode = error_y_mode,
color = 'country',
title = f'Using error {error_y_mode}',
markers = '.',
)
fig.show()
which should produce the following two plots:
I would like to modify a facetted plotly.express figure so that each trace has its own secondary y-axis. I don't want to re-create the figure from scratch using the standard Plotly-python api if possible. See exmaple below.
import plotly.express as px
input_df = px.data.tips()
fig = px.scatter(input_df,
x = 'total_bill',
y = 'tip',
color = 'day',
facet_row = 'smoker',
facet_col = 'sex',
)
fig.layout.width = 800
fig.show()
I would like to convert the above so each trace (or color) has its own secondary y-axis. So in this case, I would like 3 additional y-axes for each facet. This is my attempt but it doesn't work. There must be a better way. I would appreciate any ideas.
import plotly.graph_objects as go
yaxes = []
for trace in fig.data:
yaxisLabel = trace['yaxis']
if trace['yaxis'] in yaxes:
if yaxisLabel == 'y':
axisnumber = 0
else:
axisnumber = int(trace['yaxis'][1:])
newAxis_num = axisnumber + 100 * yaxes.count(yaxisLabel)
exec(f"fig.layout.update(yaxis{newAxis_num} = go.layout.YAxis(overlaying='y', side='right'))")
trace.update({'yaxis': f'y{newAxis_num}'})
yaxes.append(yaxisLabel)
Hi is it possible to have two different bubble types representing two different values from the same dataframe?
Currently my code is as follows:
covid = pd.read_csv('covid_19_data.csv')
fig = px.scatter_geo(covid, locations="Country/Region", locationmode="country names",animation_frame = "ObservationDate", hover_name = "Country/Region", size = "Confirmed", size_max = 100, projection= "natural earth")
Which produces the following output:
Map output
Is it possible to get it to show two different bubbles, one for confirmed cases and another for tweets? The data frame I'm working with is shown here:
Dataframe
Sure! You can freely add another dataset from px.scatter_geo() on an existing px.scatter_geo() using:
fig=px.scatter_geo()
fig.add_traces(fig1._data)
fig.add_traces(fig2._data)
Where fig1._data comes from a setup similar to yours in:
fig = px.scatter_geo(covid, locations="Country/Region", locationmode="country names",animation_frame = "ObservationDate", hover_name = "Country/Region", size = "Confirmed", size_max = 100, projection= "natural earth")
Since you haven't provided a dataset I'll use px.data.gapminder() and use the columns pop and gdpPercap, where the color of the latter is set to 'rgba(255,0,0,0.1)' which is a transparent red:
Complete code:
import plotly.express as px
df = px.data.gapminder().query("year == 2007")
fig1 = px.scatter_geo(df, locations="iso_alpha",
size="pop", # size of markers, "pop" is one of the columns of gapminder
)
fig2 = px.scatter_geo(df, locations="iso_alpha",
size="gdpPercap", # size of markers, "pop" is one of the columns of gapminder
)
# fig1.add_traces(fig2._data)
# fig1.show()
fig=px.scatter_geo()
fig.add_traces(fig1._data)
fig.add_traces(fig2._data)
fig.data[1].marker.color = 'rgba(255,0,0,0.1)'
f = fig.full_figure_for_development(warn=False)
fig.show()
Please let me know how this works out for you.
The post Plotly: Annotate marker at the last value in line chart
shows how to annotate end of lines with text and an individual marker. But how can you do the same thing for multiple lines and at the same time set the associated text and markers to match the color of all lines?
Example plot:
Code with sample dataset:
# imports
import pandas as pd
import plotly.express as px
# data
df = px.data.stocks()
colors = px.colors.qualitative.T10
# plotly
fig = px.line(df,
x = 'date',
y = [c for c in df.columns if c != 'date'],
template = 'plotly_dark',
color_discrete_sequence = colors,
title = 'Stocks',
)
fig.show()
You can address the features of each trace and build new traces for your end markers and text through:
for i, d in enumerate(fig.data):
fig.add_scatter(x=[d.x[-1]], y = [d.y[-1]], [...])
If you've specified colors when building your figure you can also retrieve trace colors and set colors for markers and fonts like this:
textfont = dict(color=d.line.color),
marker = dict(color = d.line.color, size = 12)
Plot:
The figure was being a bit crowded so I dropped one of the stocks. I also made room for the annotations by changing the position of the legend through fig.layout.legend.x = -0.3
Complete code:
# imports
import pandas as pd
import plotly.express as px
# data
df = px.data.stocks()
df = df.drop('AMZN', axis = 1)
colors = px.colors.qualitative.T10
# plotly
fig = px.line(df,
x = 'date',
y = [c for c in df.columns if c != 'date'],
template = 'plotly_dark',
color_discrete_sequence = colors,
title = 'Stocks',
)
# move legend
fig.layout.legend.x = -0.3
# add traces for annotations and text for end of lines
for i, d in enumerate(fig.data):
fig.add_scatter(x=[d.x[-1]], y = [d.y[-1]],
mode = 'markers+text',
text = d.y[-1],
textfont = dict(color=d.line.color),
textposition='middle right',
marker = dict(color = d.line.color, size = 12),
legendgroup = d.name,
showlegend=False)
fig.show()
I have a Scatter chart and I need to trace the bisector line on it. I'm wondering if there is a automated way on Plotly to generate that, or a simplified way to calculate the equation in python to generate the list of values and trace the line.
My code:
trace1 = go.Scatter(
x = eixo_x, # My list of values for 'x'
y = eixo_y, # My list of values for 'y'
mode = 'markers',
marker = dict(color = 'rgb(0, 176, 240)')
)
dados = [trace1]
layout = go.Layout(
title = 'Unitários Observados | Unitários Estimados',
autosize = False,
width = 1000,
height = 500,
xaxis = dict(
showgrid = True),
yaxis = dict(
tickmode = 'array',
showgrid = True
)
)
fig = go.Figure(data = dados, layout = layout)
fig.show()
My Plot:
Now I need to plot a line on diagonal, the bisector.
EDIT
There are a few questions about bisector, but not for Plotly.
EDIT 2
In geometry, bisection is the division of something into two equal or congruent parts, usually by a line, which is then called a bisector. Wikipedia
Example:
I didn't use an equation or an automated function from Plotly but the following code solved my problem temporarily:
I've setted the line limits for x and y getting the min and max from each list:
# Trace 2
line_x = [min(eixo_x), max(eixo_x)]
line_y = [min(eixo_y), max(eixo_y)]
And added a second trace for it:
trace2 = go.Scatter(
x = line_x,
y = line_y,
mode = 'lines',
marker = dict(color = 'rgb(127, 127, 127)'),
line = dict(dash = 'dash')
)
Result: