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.
Related
I am trying to use plotly to plot a graph similar to the one here below:
Unfortunately I am only able to plot something like this
What I would like is to have normal boundaries (upper and lower defined by two dataframe columns and only one entry in the legend.
import plotly.graph_objs as go
# Create a trace for the lower bound
trace1 = go.Scatter(x=df.index,
y=df['lower'],
name='Lower Bound',
fill='tonexty',
fillcolor='rgba(255,0,0,0.2)',
line=dict(color='blue'))
# Create a trace for the median
trace2 = go.Scatter(x=df.index,
y=df['median'],
name='median',
line=dict(color='blue', width=2))
# Create a trace for the upper bound
trace3 = go.Scatter(x=df.index,
y=df['upper'],
name='Upper Bound',
fill='tonexty',
fillcolor='rgba(255,0,0,0.2)',
line=dict(color='blue'))
# Create the layout
layout = go.Layout(xaxis=dict(title='Date'),
yaxis=dict(title='title'))
# Create the figure with the three traces and the layout
fig = go.Figure(data=[trace1, trace2, trace3], layout=layout)
context['pltyplot'] = pltyplot(fig, output_type="div")
I want to use plotly because I am integrating the resulting figure into a django web page and plotly enables, with the las line, to import the whole object in a clean, simple and interactive way into the poge.
Any ideas?
You can try this code:
import plotly.graph_objs as go
x = [1, 2, 3, 4, 5]
y = [2, 4, 5, 3, 6]
# Define the confidence interval
interval = 0.6 * np.std(y) / np.mean(y)
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='Line'))
fig.add_trace(go.Scatter(x=x+x[::-1],
y=y+[i + interval for i in y[::-1]],
fill='toself',
fillcolor='rgba(0,100,80,0.2)',
line=dict(width=0),
showlegend=False))
fig.add_trace(go.Scatter(x=x+x[::-1],
y=y+[i - interval for i in y[::-1]],
fill='toself',
fillcolor='rgba(0,100,80,0.2)',
line=dict(width=0),
showlegend=False))
fig.show()
I have a linegraph with twolines it in. On the x-Axis there is the time, on the y-Axes the values. On the y-Axis I want to set the space between the ticks manually.
My data is very dense in the range from 0 - 5, so I want the ticks in this range to be far away from each other in order distinguish between the two lines plotted in the graph.
Between 5 - 10 my data has more or less the same values, so the ticks can be closer together here.
From 10 - 15 need to spread the ticks again because my data is dense here.
I tried setting the values of the ticks manually, but that does not add/remove space/height of the ticks
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
df['Date']=pd.to_datetime(df['Date'])
dfg = df.groupby([pd.Grouper(key='Date', freq='M'), 'direction']).size().to_frame('counts')
dfg.reset_index(inplace=True)
layout = Layout(
title='Foo',
plot_bgcolor='rgba(0,0,0,0)',
yaxis = dict(
tickmode = 'array',
tickvals = [0, 0.5, 1, 1.5, ..., 5, 6, 7, ..., 10.5, 11, 11.5, 12, ...],
)
)
fig = go.Figure()
for d,c in zip(dfg['direction'].unique(), ['red','green']):
dfs = dfg.query('direction == #d')
fig.add_trace(
go.Scatter(
x=dfs['Date'],
y=dfs['counts'],
mode='lines',
line=dict(
color=c,
width=3
),
name=d
)
)
fig.show()
Note: The data I added here is not my real data. It's just some data to work with.
You need to scale your y data as you want, and then provide the ticks values and tick text
Assume:
y=[1,1.1,1.2,1.3,5,10,11,11.1,11.2,11.3]
y_trans=custom_trans(y) -> [1,2,3,4,5,6,7,8,9,10] # index
----------
go.Scatter(,y=y_trans,)
----------
fig.update_yaxes(
ticktext=["1", "1.1", "1.2", "5","10", ...],
tickvals=[1,2,3,5,6,..] #index position from y_trans
)
This is a very weird request though, and I would rather plot the difference in the two lines if it makes sense, or choose another method of visualizing, try log y axis?
I've been struggling with this seemingly simple task: How to align two x axis with related data. In my case one axis is in Celsius and the other in Fahrenheit.
What I want to achieve is to obtain alignment of the two x axis so that:
32°F = 0°C
And
50°F = 10°C
With this relation, the two datasets will be aligned in terms of temperature.
I want to have both unit sets on the same graph so that the viewer can interpret the data according to the units they are used to.
Here is my code:
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from plotly.graph_objs.layout import YAxis,XAxis,Margin
layout = go.Layout(
title="Double X Axis Example",
xaxis=XAxis(
title="Celcius"
),
xaxis2 = XAxis(
title="Fahrenheits",
overlaying= 'x',
side= 'top',
),
yaxis=dict(
title="Y values"
),
)
# Create figure with secondary x-axis
fig = go.Figure(layout=layout)
# Add traces
fig.add_trace(
go.Scatter(x=[10, 20, 30], y=[4.5, 6, 5], name="data set in celcius"),
)
fig.add_trace(
go.Scatter(x=[40, 60, 80], y=[4, 5, 6.5], name="data set in fahrenheit", xaxis='x2'),
)
fig.show()
Here is the resulting figure with the unaligned axes (10°C = 40°F !?):
Thank you,
In this case it might help to set the ranges for the x-axes, something like this:
fig.add_trace(
go.Scatter(x=[10, 20, 30], y=[4.5, 6, 5,], name="data set in celcius",xaxis="x1"),
)
fig.add_trace(
go.Scatter(x=[40, 60, 80], y=[4, 5, 6.5], name="data set in fahrenheit", xaxis='x2'),
)
fig.update_layout(
xaxis1=dict(range=[0, 100]),
xaxis2=dict(range=[32, 212]),
)
...possibly calculating the limit needed of x1 and then base x2 limit on that.
This is my solution and code to your concern. Here, I set the range of the first and second x axes to [0, 100] and [32, 212], respectively. To align the two axes, I made 26 tick marks for both axes and they are aligned because of the equal number of tick marks. Having an equal number of tick marks for both axes (and equal ranges) is crucial so that the aligned numbers are actually equal. Assuming that most data sets that will be plotted are between 0 and 100 degrees Celsius (for data in Celsius) --- or 32 and 212 degrees Fahrenheit (for data in Fahrenheit) --- I believe this solution overflows the data and the traces won't cover the full x ranges. Plot of the graph here.
import numpy as np
import plotly.graph_objects as go
arr1 = np.array([10, 20, 30])
arr2 = np.array([4.5, 6, 5])
arr3 = np.array([40, 60, 80])
arr4 = np.array([4, 5, 6.5])
fig = go.Figure(go.Scatter( x=arr1, y=arr2, name='data set in celsius' ) )
fig.add_trace(go.Scatter( x=arr3, y=arr4, xaxis='x2', name='data set in fahrenheit' ))
fig.update_layout(title_text='Double X Axis Example',
legend=dict(yanchor='top', y=0.875, xanchor='right', x=1),
yaxis=dict(domain = [0.05, 0.875], title='Y values', spikemode='toaxis', spikesnap='cursor'), template='plotly_dark',
xaxis =dict(position = 0, title='Celsius', spikemode='across', spikesnap='cursor',
tickmode='array', tickvals=np.linspace(0,100,26), range=[0,100]),
xaxis2=dict(position = 0.9, title='Fahrenheit', anchor='free', overlaying='x', side='top', tickmode='array',
tickvals=np.linspace(32,212,26), range=[32,212], spikemode='across', spikesnap='cursor' )
)
fig.show()
I'm trying to plot a polar chart with python and plotly to show the orientation of fibers in an 2D image (see the code below).
It would be great if you could show me how to change the angular axis, currently ranging from 0° to 360°, to match my data ranging from -90° to 90°.
Below are example images of a half polar chart, the format of my data, and my code.
import plotly.graph_objs as go
from plotly import plotly
import plotly.offline as offline
import numpy as np
# data
x= np.genfromtxt(see data image)
y= np.genfromtxt(see data image)
trace = [
go.Scatterpolar(
r = [y], #radial coordinates
theta = [x], #angular coordinates
mode = 'markers',
marker = dict(
color = 'peru'
)
)
]
layout = go.Layout(
showlegend = True,
polar = dict(
domain = dict( # set chart size and position
x = [0, 0.8],
y = [0.3, 0.8]),
sector = [0, 180], # set chart shape (half or full)
angularaxis = dict(
thetaunit = "degrees",
dtick = 10),
radialaxis = dict(
range = [1, 8000])
))
fig = go.Figure(data=trace, layout=layout)
offline.plot(fig)
x-y data
half polar chart for fiber orientation
Thank you very much DatHydroGuy! I completely rewrote the code with your changes and it is working now. Below is the code and an image of the output. NOICE! Thanks again, HydroGuy, for you help!
If somebody knows how to rotate it (by 90° counterclockwise) and mirror it (-90 left, 0 top, 90 right) please let me know. I tried rotation= and direction= commands, but they did not work and collide with the sector= command for setting the angular axis range from -90 to 90.
Cheers, Ron
import plotly.graph_objs as go
from plotly import plotly
import plotly.offline as offline
import numpy as np
import plotly
# data
x= np.genfromtxt("data.csv", delimiter=",", usecols=(0), skip_header=1, encoding = 'unicode_escape')
y= np.genfromtxt("data.csv", delimiter=",", usecols=(1), skip_header=1, encoding = 'unicode_escape')
trace = [
go.Scatterpolar(
r = [float(a) for a in y], #radial coordinates
theta = [float(b) for b in x], #angular coordinates
mode = 'lines',
marker = dict(
color = 'peru'
)
)
]
layout = go.Layout(
showlegend = True,
legend=dict(
x=1),
polar = dict(
domain = dict( # set chart size and position
x = [0, 1],
y = [0, 1]),
sector = [-90,90], # set chart shape (half or full)
angularaxis = dict(
thetaunit = "degrees",
dtick = 10,
#rotation = -90, #does not work
#direction = "clockwise" # does not work
),
radialaxis = dict(
range = [1, 6500])
))
fig = go.Figure(data=trace, layout=layout)
offline.plot(fig)
plotly half polar plot
OK, so I only got output by making the following changes:
Changed the go.Layout sector=[0, 180] to sector=[-90, 90]
Changed the go.Scatterplot r=[y] to r=[float(a) for a in y]
Changed the go.Scatterplot theta=[x] to theta=[float(b) for b in x]
The first change created the range that you require (-90 to 90)
The 2nd and 3rd changes converted the results from np.genfromtext() from strings to numeric (although these changes may not be necessary if your data is already numerical within x and y).
My code now looks like this:
import plotly.graph_objs as go
import plotly.offline as offline
import numpy as np
# data
x = np.genfromtxt([str(i) for i in range(-90, 91)])
y = np.genfromtxt([str(i * 25 + np.random.randint(1000, 2500)) for i in range(0, 181)])
trace = [
go.Scatterpolar(
r=[float(a) for a in y], # radial coordinates
theta=[float(b) for b in x], # angular coordinates
thetaunit="degrees",
mode='markers',
marker=dict(
color='peru'
)
)
]
layout = go.Layout(
showlegend=True,
polar=dict(
domain=dict( # set chart size and position
x=[0, 0.8],
y=[0.3, 0.8]),
sector=[0, 1800], # set chart shape (half or full)
angularaxis=dict(
thetaunit="degrees",
dtick=10,
rotation=90,
direction='clockwise'),
radialaxis=dict(
range=[1, 8000])
)
)
fig = go.Figure(data=trace, layout=layout)
offline.plot(fig)
These changes were sufficient to produce the following:
Is that what you are looking for?
I have the following code;
y = errnums
err_box = Box(
y=y,
name='Error Percent',
boxmean='sd',
marker=Marker(color='red'),
boxpoints='all',
jitter=0.5,
pointpos=-2.0
)
layout = Layout(
title='Error BoxPlot',
height=500,
width=500
)
fig = Figure(data=Data([err_box]), layout=layout)
plotly.image.save_as(fig, os.path.join(output_images, 'err_box.png'))
Which generates the following image;
What I would like to do is the following two things;
1) Add % next to the y-axis numbers. (Instead of having a traditional y-axis label saying "Error (%)")
2) Label all the vital points: mean, first quartile, third quartile, and stdev. Ideally the label would be a 4 sig-fig ('.2f') number next to the line.
Also, the stdev is the dotted line, and the diamond represents 1 sigma? 2 sigma?
For labels, try annotations. You'll have to compute the quartiles and mean yourself to position the labels.
Simple example:
import plotly.plotly as py
from plotly.graph_objs import *
data = Data([
Box(
y=[0, 1, 1, 2, 3, 5, 8, 13, 21],
boxpoints='all',
jitter=0.3,
pointpos=-1.8
)
])
layout = Layout(
annotations=Annotations([
Annotation(
x=0.3,
y=8.822,
text='3rd Quartile',
showarrow=False,
font=Font(
size=16
)
)
])
)
fig = Figure(data=data, layout=layout)
plot_url = py.plot(fig)
Simple Python boxplot
I recommend adding and positioning the annotations in the Plotly workspace, and then viewing the generated code:
The diamond shows the mean, and +- 1 standard deviation away from it.
It's not currently possible to add a % to the y-axis labels.