Can we plot another layer of plot over a visualization using plotly through python.?
I am trying to join two points over a bubble chart.
You should be aware of the concept of traces, where we can place two types of charts in the same graph. To see the concept in action refer Multiple Chart Types in Same Graph. Just as a starting point please refer the below code snippet which does what you want.
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.graph_objs as go
from datetime import datetime
init_notebook_mode(connected=True)
trace0 = go.Scatter(
x=[1, 2, 3, 4],
y=[10, 11, 12, 13],
mode='markers',
marker=dict(
size=[40, 60, 80, 100],
)
)
trace1 = go.Scatter(
x = [1, 2, 3, 4],
y = [10, 11, 12, 13],
line = dict(
color = ('rgb(22, 96, 167)'),
width = 4,
dash = 'line')
)
data = [trace0, trace1]
iplot(data, filename='bubblechart-size')
The line that you require can also be generated using plotly shapes. Please read more about this here
Related
As per the Plotly website, in a simple line chart one can change the legend entry from the column name to a manually specified string of text. For example, this code results in the following chart:
import pandas as pd
import plotly.express as px
df = pd.DataFrame(dict(
x = [1, 2, 3, 4],
y = [2, 3, 4, 3]
))
fig = px.line(
df,
x="x",
y="y",
width=800, height=600,
labels={
"y": "Series"
},
)
fig.show()
label changed:
However, when one plots multiple columns to the line chart, this label specification no longer works. There is no error message, but the legend entries are simply not changed. See this example and output:
import pandas as pd
import plotly.express as px
df = pd.DataFrame(dict(
x = [1, 2, 3, 4],
y1 = [2, 3, 4, 3],
y2 = [2, 4, 6, 8]
))
fig = px.line(
df,
x="x",
y=["y1", "y2"],
width=800, height=600,
labels={
"y1": "Series 1",
"y2": "Series 2"
},
)
fig.show()
legend entries not changed:
Is this a bug, or am I missing something? Any idea how this can be fixed?
In case anybody read my previous post, I did some more digging and found the solution to this issue. At the heart, the labels one sees over on the right in the legend are attributes known as "names" and not "labels". Searching for how to revise those names, I came across another post about this issue with a solution Legend Label Update. Using that information, here is a revised version of your program.
import pandas as pd
import plotly.express as px
df = pd.DataFrame(dict(
x = [1, 2, 3, 4],
y1 = [2, 3, 4, 3],
y2 = [2, 4, 6, 8]
))
fig = px.line(df, x="x", y=["y1", "y2"], width=800, height=600)
fig.update_layout(legend_title_text='Variable', xaxis_title="X", yaxis_title="Series")
newnames = {'y1':'Series 1', 'y2': 'Series 2'} # From the other post
fig.for_each_trace(lambda t: t.update(name = newnames[t.name]))
fig.show()
Following is a sample graph.
Try that out to see if that addresses your situation.
Regards.
I'm trying to the image shown below and I thought python would be a good idea to do this but I'm not sure. I want to randomize lots of football players' stats, make a radar chart for each and save the charts as images.
But the plotly radar charts are not so stylish and I really want to make something stylish. How to turn the below demo code into the reference image and is it possible?
Here's a demo code:
import plotly.graph_objects as go
categories = ['Defending','Speed','Attacking',
'Technical', 'Team play']
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=[1, 5, 2, 2, 3],
theta=categories,
fill='toself',
name='Alice'
))
fig.add_trace(go.Scatterpolar(
r=[4, 3, 2.5, 1, 2],
theta=categories,
fill='toself',
name='Bob'
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 5]
)),
showlegend=False
)
fig.show()
From the documentation for polar layout, it seems that Plotly does not offer much options when it comes the grid shape itself. However, Plotly allows you to create your own templates/themes or examine built-in themes.
As a starting point, you should probably analyze the plotly_dark theme as it has some features similar to your picture.
simple example with built-in template
dataset.csv
categories,player,points
Defending,alice,1
Speed,alice,5
Attacking,alice,2
Technical,alice,2
Team play,alice,3
Defending,bob,4
Speed,bob,3
Attacking,bob,2.5
Technical,bob,1
Team play,bob,2
code
import plotly.express as px
import pandas as pd
df = pd.read_csv("dataset.csv")
fig = px.line_polar(df, r="points",
theta="categories",
color="player",
line_close=True,
color_discrete_sequence=["#00eb93", "#4ed2ff"],
template="plotly_dark")
fig.update_polars(angularaxis_showgrid=False,
radialaxis_gridwidth=0,
gridshape='linear',
bgcolor="#494b5a",
radialaxis_showticklabels=False
)
fig.update_layout(paper_bgcolor="#2c2f36")
fig.show()
With the above code I don't think it is possible to modify the color of each nested shape. To be able to do so, you will probably have to create your own template and color each nested shape separately.
creating grid shape
You might have to try something similar the code below to create your desired grid shape.
import plotly.graph_objects as go
bgcolors = ["#353841", "#3f414d", "#494b5a", "#494b5a", "#58596a"]
fig = go.Figure(go.Scatterpolar(
r=[42]*8,
theta=[0, 45, 90, 135, 180, 225, 270, 315],
marker_line_width=2,
opacity=0.8,
marker=dict(color=bgcolors[0])
))
for i in range(1, 5):
fig.add_trace(go.Scatterpolar(
r=[44-6*i]*8,
theta=[0, 45, 90, 135, 180, 225, 270, 315],
marker_line_width=2,
marker=dict(color=bgcolors[i])
))
fig.update_polars(angularaxis_dtick='')
fig.update_traces(fill='toself')
fig.update_polars(angularaxis_showgrid=False,
radialaxis_showgrid=False,
radialaxis_gridwidth=0,
gridshape='linear',
radialaxis_showticklabels=False,
angularaxis_layer='above traces'
)
fig.show()
The colors are off the general shape is good.
I have two dictionaries:
days = {'a':[1,2,3], 'b':[3,4,5]}
vals = {'a':[10,20,30], 'b':[9,16,25]}
Using plotly (ideally plotly express) I would like one line plot with two lines: the first line being days['a'] vs vals['a'] and the second line being days['b'] vs vals['b']. Of course in practice I may have many more potential lines. I am not sure how to pull this off. I'm happy to make a dataframe out of this data but not sure what the best structure is.
Thanks! Apologies for a noob question.
You can try the following:
import plotly.graph_objects as go
# your data
days = {'a':[1,2,3], 'b':[3,4,5]}
vals = {'a':[10,20,30], 'b':[9,16,25]}
# generate a plot for each dictionary key
data = []
for k in days.keys():
plot = go.Scatter(x=days[k],
y=vals[k],
mode="lines",
name=k # label for the plot legend
)
data.append(plot)
# create a figure with all plots and display it
fig = go.Figure(data=data)
fig.show()
This gives:
With Plotly Express:
import plotly.express as px
import pandas as pd
days = {'a': [1, 2, 3], 'b': [3, 4, 5]}
vals = {'a': [10, 20, 30], 'b': [9, 16, 25]}
# build DataFrame
df = pd.DataFrame(columns=["days", "vals", "label"])
for k in days.keys():
df = df.append(pd.DataFrame({
"days": days[k],
"vals": vals[k],
"label": k
}))
fig = px.line(df, x="days", y="vals", color="label")
fig.show()
The result is the same as above.
I would like to plot a chart with plotly that shows only the existing values in the x-axis.
When I execute the code below, a chart that looks like in the following image appears:
The range on the x-axis as well as the range on the y-axis is evenly set from zero up to the maximal value.
import plotly.graph_objs as go
from plotly.offline import plot
xValues = [1, 2, 27, 50]
yValues = [7, 1, 2, 3]
trace = go.Scatter( x = xValues, y = yValues, mode='lines+markers', name='high limits' )
plottedData = [trace]
plot( plottedData )
Now, I would like to show only the existing values on the x axis. Related to my example, I want just the values [1, 2, 27, 50] to appear. And they should have the same space in between. Is this possible? If yes, how?
You can force the xaxis.type to be category like this:
plot( dict(data=plottedData, layout=go.Layout(xaxis = {"type": "category"} )))
I am having trouble figuring out how to label specific bubbles in a plot.ly bubble chart. I want certain "outlier" bubbles to have text written inside the bubble instead of via hover text.
Let's say I have this data:
import plotly.plotly as py
import plotly.graph_objs as go
trace0 = go.Scatter(
x=[1, 2, 3, 4],
y=[10, 11, 12, 13],
mode='markers',
marker=dict(
size=[40, 60, 80, 100],
)
)
data = [trace0]
py.iplot(data, filename='bubblechart-size')
I'd like to only add text markers on bubbles that correspond to (1,10) and (4,13). Furthermore, is it possible to control the location of text markers?
You can achieve this with annotations.
This allows you to write any text you want on the chart and reference it to your data. You can also control where the text appears using position anchors or by applying an additional calculation on top of the x and y data. For example:
x_data = [1, 2, 3, 4]
y_data = [10, 11, 12, 13]
z_data = [40, 60, 80, 100]
annotations = [
dict(
x=x,
y=y,
text='' if 4 > x > 1 else z, # Some conditional to define outliers
showarrow=False,
xanchor='center', # Position of text relative to x axis (left/right/center)
yanchor='middle', # Position of text relative to y axis (top/bottom/middle)
) for x, y, z in zip(x_data, y_data, z_data)
]
trace0 = go.Scatter(
x=x_data,
y=y_data,
mode='markers',
marker=dict(
size=z_data,
)
)
data = [trace0]
layout = go.Layout(annotations=annotations)
py.iplot(go.Figure(data=data, layout=layout), filename='bubblechart-size')
Edit
If using cufflinks, then the above can be adapted slightly to:
bubbles_to_annotate = df[(df['avg_pos'] < 2) | (df['avg_pos'] > 3)] # Some conditional to define outliers
annotations = [
dict(
x=row['avg_pos'],
y=row['avg_neg'],
text=row['subreddit'],
showarrow=False,
xanchor='center', # Position of text relative to x axis (left/right/center)
yanchor='middle', # Position of text relative to y axis (top/bottom/middle)
) for _, row in bubbles_to_annotate.iterrows()
]
df.iplot(kind='bubble', x='avg_pos', y='avg_neg', size='counts',
text='subreddit', xTitle='Average Negative Sentiment',
yTitle='Average Positive Sentiment', annotations=annotations,
filename='simple-bubble-chart')
You will still need to define the annotations since you need a conditional argument. Then pass this directly to cufflinks via annotations.