I am creating a line scatter plot using plotly python API. There are old and new data plotted in y-axis with the date in the x-axis.I would like to center the graph such that one part of the graph is old data and another half of the graph is new data. How can this be done in plotly?In the attached image, the blue one represents old and orange represents new data. How old and new can be centered such that one part of the graph is old data and another half of the graph is new data?
Plotly_Line_Scatterplot
Building on the manual axes example from the Plotly documentation:
import plotly.plotly as py
import plotly.graph_objs as go
xold=[5, 6, 7, 8]
yold=[3, 2, 1, 0]
xnew=[10, 11, 12, 13, 14, 15, 16, 17, 18]
ynew=[0, 1, 2, 3, 4, 5, 6, 7, 8]
oldData = go.Scatter(xold, yold)
newData = go.Scatter(xnew, ynew)
data = [oldData, newData]
lenOld = max(xold) - min(xold)
lenNew = max(xnew) - min(xnew)
lenX = 2*max(lenOld,lenNew)
layout = go.Layout(
xaxis=dict(
range=[min(xnew)-lenX/2, min(xnew)+lenX/2]
)
)
fig = go.Figure(data=data, layout=layout)
plot_url = py.plot(fig, filename='axes-range-manual')
For simplicity I have used integers as x-values rather than using dates but the same principle will apply.
Please note, I don't have plotly installed at present so I haven't tested this code.
Related
I have problem with sns lineplot and scatterplot. Basically what I'm trying to do is to connect dots of a scatterplot to present closest line joining mapped points. Somehow lineplot is changing width when facing points with tha same x axis values. I want to lineplot to be same, solid line all the way.
The code:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
data = {'X': [13, 13, 13, 12, 11], 'Y':[14, 11, 13, 15, 20], 'NumberOfPlanets':[2, 5, 2, 1, 2]}
cts = pd.DataFrame(data=data)
plt.figure(figsize=(10,10))
sns.scatterplot(data=cts, x='X', y='Y', size='NumberOfPlanets', sizes=(50,500), legend=False)
sns.lineplot(data=cts, x='X', y='Y',estimator='max', color='red')
plt.show()
The outcome:
Any ideas?
EDIT:
If I try using pyplot it doesn't work either:
Code:
plt.plot(cts['X'], cts['Y'])
Outcome:
I need one line, which connects closest points (basically what is presented on image one but with same solid line).
Ok, I have finally figured it out. The reason lineplot was so messy is because data was not properly sorted. When I sorted dataframe data by 'Y' values, the outcome was satisfactory.
data = {'X': [13, 13, 13, 12, 11], 'Y':[14, 11, 13, 15, 20], 'NumberOfPlanets':[2, 5, 2, 1, 2]}
cts = pd.DataFrame(data=data)
cts = cts.sort_values('Y')
plt.figure(figsize=(10,10))
plt.scatter(cts['X'], cts['Y'], zorder=1)
plt.plot(cts['X'], cts['Y'], zorder=2)
plt.show()
Now it works. Tested it also on other similar scatter points. Everything is fine :)
Thanks!
I am trying to mark the last value of the line chart with a big red dot in plotly express python, could someone please help me?
I am successful in building the line chart but not able to annotate the dot.
Below is my dataframe and I want the last value in the dataframe to be annotated.
Below is the line chart created and I want my chart to be similar to the second image in the screenshot
Code I am working with:
fig = px.line(gapdf, x='gap', y='clusterCount', text="clusterCount")
fig.show()
The suggestion from gflavia works perfectly well.
But you can also set up an extra trace and associated text by addressing the elements in the figure directly instead of the data source like this:
fig.add_scatter(x = [fig.data[0].x[-1]], y = [fig.data[0].y[-1]])
Plot 1
Complete code:
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
gapdf = pd.DataFrame({
'clusterCount': [1, 2, 3, 4, 5, 6, 7, 8],
'gap': [-15.789, -14.489, -13.735, -13.212, -12.805, -12.475, -12.202, -11.965]
})
fig = px.line(gapdf, x='gap', y='clusterCount')
fig.add_scatter(x = [fig.data[0].x[-1]], y = [fig.data[0].y[-1]],
mode = 'markers + text',
marker = {'color':'red', 'size':14},
showlegend = False,
text = [fig.data[0].y[-1]],
textposition='middle right')
fig.show()
You could overlay an additional trace for the last data point with plotly.graph_objects:
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
gapdf = pd.DataFrame({
'clusterCount': [1, 2, 3, 4, 5, 6, 7, 8],
'gap': [-15.789, -14.489, -13.735, -13.212, -12.805, -12.475, -12.202, -11.965]
})
fig = px.line(gapdf, x='gap', y='clusterCount')
fig.add_trace(go.Scatter(x=[gapdf['gap'].iloc[-1]],
y=[gapdf['clusterCount'].iloc[-1]],
text=[gapdf['clusterCount'].iloc[-1]],
mode='markers+text',
marker=dict(color='red', size=10),
textfont=dict(color='green', size=20),
textposition='top right',
showlegend=False))
fig.update_layout(plot_bgcolor='white',
xaxis=dict(linecolor='gray', mirror=True),
yaxis=dict(linecolor='gray', mirror=True))
fig.show()
I am learning altair to add interactivity to my plots. I am trying to recreate a plot I do in matplotlib, however altair is adding noise to my curves.
this is my dataset
df1
linked here from github: https://raw.githubusercontent.com/leoUninova/Transistor-altair-plots/master/df1.csv
This is the code:
fig, ax = plt.subplots(figsize=(8, 6))
for key, grp in df1.groupby(['Name']):
y=grp.logabsID
x=grp.VG
ax.plot(x, y, label=key)
plt.legend(loc='best')
plt.show()
#doing it directly from link
df1='https://raw.githubusercontent.com/leoUninova/Transistor-altair-plots/master/df1.csv'
import altair as alt
alt.Chart(df1).mark_line(size=1).encode(
x='VG:Q',
y='logabsID:Q',
color='Name:N'
)
Here is the image of the plots I am generating:
matplotlib vs altair plot
How do I remove the noise from altair?
Altair sorts the x axis before drawing lines, so if you have multiple lines in one group it will often lead to "noise", as you call it. This is not noise, but rather an accurate representation of all the points in your dataset shown in the default sort order. Here is a simple example:
import numpy as np
import pandas as pd
import altair as alt
df = pd.DataFrame({
'x': [1, 2, 3, 4, 5, 5, 4, 3, 2, 1],
'y': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'group': [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
})
alt.Chart(df).mark_line().encode(
x='x:Q',
y='y:Q'
)
The best way to fix this is to set the detail encoding to a column that distinguishes between the different lines that you would like to be drawn individually:
alt.Chart(df).mark_line().encode(
x='x:Q',
y='y:Q',
detail='group:N'
)
If it is not the grouping that is important, but rather the order of the points, you can specify that by instead providing an order channel:
alt.Chart(df.reset_index()).mark_line().encode(
x='x:Q',
y='y:Q',
order='index:Q'
)
Notice that the two lines are connected on the right end. This is effectively what matplotlib does by default: it maintains the index order even if there is repeated data. Using the order channel for your data produces the result you're looking for:
df1 = pd.read_csv('https://raw.githubusercontent.com/leoUninova/Transistor-altair-plots/master/df1.csv')
alt.Chart(df1.reset_index()).mark_line(size=1).encode(
x='VG:Q',
y='logabsID:Q',
color='Name:N',
order='index:Q'
)
The multiple lines in each group are drawn in order connected at the ends, just as they are in matplotlib.
Ok, So I want to go one step further. I don't know if it is possible with a dash.
I want to create a form ( probably WTForm from Flask ).
The form should have date and annotation/comments section.
When someone submits a form, it will save to the database.
Then dash will read it and show on the graph.
My graph looks like that:
On the x-axis will be date from FlaskForm representing Event that it was stored in the database, and annotation will be showed in the graph itself when I hover to that exact date
Something similar to this one:
And now, can you please tell me if it's possible? What tools should I use it? It's just a concept, but I think will be helpful for everyone.
In plotly you can display text using annotation. Example:
import plotly.plotly as py
import plotly.graph_objs as go
trace1 = go.Scatter(
x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
y=[0, 1, 3, 2, 4, 3, 4, 6, 5]
)
trace2 = go.Scatter(
x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
y=[0, 4, 5, 1, 2, 2, 3, 4, 2]
)
data = [trace1, trace2]
layout = go.Layout(
showlegend=False,
annotations=[
dict(
x=2,
y=5,
xref='x',
yref='y',
text='max',
showarrow=True,
arrowhead=7,
ax=0,
ay=-40
)
]
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
Ref : https://plot.ly/python/text-and-annotations
Hope that answers your question. Also refer to mode='lines+markers+text' in scatter plot(Adding Text to Data in Line and Scatter Plots section of plotly doc)
Pretty late here, but check out dbc.Input from dash-bootstrap-components.
https://dash-bootstrap-components.opensource.faculty.ai/l/components/input
There are form types, inputs, etc.
How I would do it is add a few inputs, etc. as well as a submit button. The submit button would trigger the function that creates the graphs, adds the relevant things, and returns the figure to the graph.
I have made a scatterplot using Plotly (python), and i want to connect the dots using something similar to geom_smooth() function.
Something like below image :
You should be able to do it by setting the shape='spline' when defining the line. here is the plotly example
trace2 = go.Scatter(
x=[1, 2, 3, 4, 5],
y=[6, 8, 7, 8, 6],
mode='lines+markers',
name="'spline'",
text=["tweak line smoothness<br>with 'smoothing' in line object"],
hoverinfo='text+name',
line=dict(
shape='spline'
)
)
See an example here: plotly line charts