Plotly override legend names without traces - pandas

I'm trying to change the legend names and I've found many answers but none of them works if you are not using traces. I learned to change the legend title but not the names.
Here it is my code, hopefully somebody can help:
import pandas as pd
import plotly.express as px
import numpy as np
def camasRegion():
df = pd.read_csv('https://raw.githubusercontent.com/MinCiencia/Datos-COVID19/master/output/producto52/Camas_UCI.csv')
dates = df.columns #for some reason I can't use this as x axis
habilitadas = []
ocupadasCovid = []
ocupadasNoCovid = []
region = 'Ñuble'
for i in range(len(df)):
if df.values[i][0] == region:
if df.values[i][1] == 'Camas UCI habilitadas':
for x in range(len(df.columns)):
habilitadas.append(df.values[i][x])
if df.values[i][1] == 'Camas UCI ocupadas COVID-19':
for x in range(len(df.columns)):
ocupadasCovid.append(df.values[i][x])
if df.values[i][1] == 'Camas UCI ocupadas no COVID-19':
for x in range(len(df.columns)):
ocupadasNoCovid.append(df.values[i][x])
fig = px.line(df,
y = [habilitadas, ocupadasCovid, ocupadasNoCovid],
x = range(len(fechas)), #I'm doing this because x = dates doesn't work
title='Camas por región: ('+region+')',)
fig.add_annotation(
x = 1, y = -0.1,
text = 'Fuente: Datos obtenidos desde el Ministerio de Ciencia.',
showarrow = False, xref='paper', yref='paper',
xanchor='right', yanchor='auto', xshift=0, yshift=-20
)
fig.update_layout(
legend_title_text='Estado de cama',
xaxis_title="Días",
yaxis_title="Cantidad de camas",
)
fig.show()
camasRegion()

You can't use dates, because df.columns besides dates contains strings Region and Serie. I simplified your code, it also made it more readable. Try this and let me know, if it still not working for you.
import pandas as pd
import plotly.graph_objects as go
import numpy as np
def camasRegion():
df = pd.read_csv('https://raw.githubusercontent.com/MinCiencia/Datos-COVID19/master/output/producto52/Camas_UCI.csv')
region = "Ñuble"
target_region = df.query('Region == #region').drop('Region', axis=1).set_index('Serie').T
chart = []
for i in target_region:
if i != 'Camas base (2019)': #or you can easily drop it from your dataset
chart += [go.Scatter(x=target_region.index,y=target_region[i], name=i, mode='lines')]
fig = go.Figure(chart)
fig.update_layout(title={'text':f'Camas por región: ({region})', 'x':.45},
template='plotly_white', hovermode='x',
legend_title_text='Estado de cama',
xaxis_title="Días",
yaxis_title="Cantidad de camas")
fig.add_annotation(
x = 1, y = -0.1,
text = 'Fuente: Datos obtenidos desde el Ministerio de Ciencia.',
showarrow = False, xref='paper', yref='paper',
xanchor='right', yanchor='auto', xshift=0, yshift=-20
)
fig.show()
camasRegion()
The result:

Related

Lambdify a function in two variables and plot a surface

I have a function f(x,y) where t is a parameter. I'm trying to plot the function where t = 1 for x and y values ranging from -5 to 5. The plot doesn't render.
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook
C = sv.CoordSys3D("")
x, y, z = C.base_scalars()
t = sp.symbols("t")
f = sp.sin(2*sp.pi*t)*sp.exp(-(x-3*sp.sin(sp.pi*t))**2 -(y-3*sp.cos(sp.pi*t))**2)
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(projection='3d')
X = np.linspace(-5,5,100)
Y = np.linspace(-5,5,100)
xvals, yvals = np.meshgrid(X,Y)
zvals = sp.lambdify((x,y),f.subs(t,1),"numpy")(xvals,yvals)
ax.plot_surface(xvals,yvals,zvals)
plt.show()
I get an error 'int' object has no attribute 'ndim' which I don't know how to solve.
The problem is that when you execute f.subs(t,1) it returns a number (zero in this case). So, f=0 is the expression that you are going to lambdify. Let's see the function generated by lambdify:
import inspect
print(inspect.getsource(sp.lambdify((x,y),f.subs(t,1),"numpy")))
# def _lambdifygenerated(Dummy_25, Dummy_24):
# return 0
So, no matter the values and shape of xvals and yvals, that numerical function will always return 0, which is an integer number.
However, ax.plot_surface requires zvals to have the same shape as xvals or yval. Luckily, we can easily fix that with a simple if statement:
import sympy as sp
import sympy.vector as sv
import numpy as np
import matplotlib.pyplot as plt
C = sv.CoordSys3D("")
x, y, z = C.base_scalars()
t = sp.symbols("t")
f = sp.sin(2*sp.pi*t)*sp.exp(-(x-3*sp.sin(sp.pi*t))**2 -(y-3*sp.cos(sp.pi*t))**2)
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(projection='3d')
X = np.linspace(-5,5,100)
Y = np.linspace(-5,5,100)
xvals, yvals = np.meshgrid(X,Y)
zvals = sp.lambdify((x,y),f.subs(t,1),"numpy")(xvals,yvals)
# if zvals is just a number, create a proper matrix
if not isinstance(zvals, np.ndarray):
zvals = zvals * np.ones_like(xvals)
ax.plot_surface(xvals,yvals,zvals)
plt.show()
The fact that this doesn't render is bug in lambdify that it doesn't work well for constant expressions.
Your real problem though is that the expression you are trying to plot is just zero:
In [5]: f
Out[5]:
2 2
- (x_ - 3⋅sin(π⋅t)) - (y_ - 3⋅cos(π⋅t))
ℯ ⋅sin(2⋅π⋅t)
In [6]: f.subs(t, 1)
Out[6]: 0

Get Value from Contourplot - Python Matplotlib

i have a problem with my contourplot. I have messured data from experimental work, then i interpolated and plot it with matplotlib contourplot. Now i want to validate my interpolation.
For this validation i need to know the plottet value from a specific (x,y) point out of my contourplot. Due to i want to check how close my interpolation at (x,y) to my messured data at (x,y) is.
At the end i want to plot the difference over x.
i hope you understand my problem and can help me!
thanks a lot!
import pandas as pd
import numpy as np
from matplotlib.pyplot import griddata
from matplotlib.pyplot import plot
df = pd.read_excel("my_work.xlsx")
x = df.loc["x_messured" ]
y = df.loc["y_messured" ]
z = df.loc["z_messured" ]
x_interp = np.linspace(0, max(x), 200)
y_interp = np.linspace(0, max(y), 200)
z2d = griddata((x, y), z, (x_interp[None,:], y_interp[:,None]))
matplotlib.pyplot.figure()
cs = plt.contour(x_interp, y_interp, z2d)
csf = plt.contourf(x_interp, y_interp, z2d, cmap="viridis")
diff = []
for q in range(len(x)):
diff.append( abs( z[q] - get_from_z2d(x[q], y[q]) ) )
plot(x, diff)
I need the function get_from_z2d()...

How to change the tick labels on a a seaborn joint plot [duplicate]

I am trying to use a log scale as the margin plots for my seaborn jointplot. I am usings set_xticks() and set_yticks(), but my changes do not appear. Here is my code below and the resulting graph:
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import seaborn as sns
import pandas as pd
tips = sns.load_dataset('tips')
female_waiters = tips[tips['sex']=='Female']
def graph_joint_histograms(df1):
g=sns.jointplot(x = 'total_bill',y = 'tip', data = tips, space = 0.3,ratio = 3)
g.ax_joint.cla()
g.ax_marg_x.cla()
g.ax_marg_y.cla()
for xlabel_i in g.ax_marg_x.get_xticklabels():
xlabel_i.set_visible(False)
for ylabel_i in g.ax_marg_y.get_yticklabels():
ylabel_i.set_visible(False)
x_labels = g.ax_joint.get_xticklabels()
x_labels[0].set_visible(False)
x_labels[-1].set_visible(False)
y_labels = g.ax_joint.get_yticklabels()
y_labels[0].set_visible(False)
y_labels[-1].set_visible(False)
g.ax_joint.set_xlim(0,200)
g.ax_marg_x.set_xlim(0,200)
g.ax_joint.scatter(x = df1['total_bill'],y = df1['tip'],data = df1,c = 'y',edgecolors= '#080808',zorder = 2)
g.ax_joint.scatter(x = tips['total_bill'],y = tips['tip'],data = tips, c= 'c',edgecolors= '#080808')
ax1 =g.ax_marg_x.get_axes()
ax2 = g.ax_marg_y.get_axes()
ax1.set_yscale('log')
ax2.set_xscale('log')
ax1.set_yscale('log')
ax2.set_xscale('log')
ax2.set_xlim(1e0, 1e4)
ax1.set_ylim(1e0, 1e3)
ax2.xaxis.set_ticks([1e0,1e1,1e2,1e3])
ax2.xaxis.set_ticklabels(("1","10","100","1000"), visible = True)
plt.setp(ax2.get_xticklabels(), visible = True)
colors = ['y','c']
ax1.hist([df1['total_bill'],tips['total_bill']],bins = 10, stacked=True,log = True,color = colors, ec='black')
ax2.hist([df1['tip'],tips['tip']],bins = 10,orientation = 'horizontal', stacked=True,log = True,color = colors, ec='black')
ax2.set_ylabel('')
Any ideas would be much appreciated.
Here is the resulting graph:
You should actually get an error from the line g.ax_marg_y.get_axes() since an axes does not have a get_axes() method.
Correcting for that
ax1 =g.ax_marg_x
ax2 = g.ax_marg_y
should give you the desired plot. The ticklabels for the log axis are unfortunately overwritten by the histogram's log=True argument. So you can either leave that out (since you already set the axes to log scale anyways) or you need to set the labels after calling hist.
import matplotlib.pyplot as plt
import seaborn as sns
tips = sns.load_dataset('tips')
def graph_joint_histograms(tips):
g=sns.jointplot(x = 'total_bill',y = 'tip', data = tips, space = 0.3,ratio = 3)
g.ax_joint.cla()
g.ax_marg_x.cla()
g.ax_marg_y.cla()
for xlabel_i in g.ax_marg_x.get_xticklabels():
xlabel_i.set_visible(False)
for ylabel_i in g.ax_marg_y.get_yticklabels():
ylabel_i.set_visible(False)
x_labels = g.ax_joint.get_xticklabels()
x_labels[0].set_visible(False)
x_labels[-1].set_visible(False)
y_labels = g.ax_joint.get_yticklabels()
y_labels[0].set_visible(False)
y_labels[-1].set_visible(False)
g.ax_joint.set_xlim(0,200)
g.ax_marg_x.set_xlim(0,200)
g.ax_joint.scatter(x = tips['total_bill'],y = tips['tip'],data = tips,
c = 'y',edgecolors= '#080808',zorder = 2)
g.ax_joint.scatter(x = tips['total_bill'],y = tips['tip'],data = tips,
c= 'c',edgecolors= '#080808')
ax1 =g.ax_marg_x
ax2 = g.ax_marg_y
ax1.set_yscale('log')
ax2.set_xscale('log')
ax2.set_xlim(1e0, 1e4)
ax1.set_ylim(1e0, 1e3)
ax2.xaxis.set_ticks([1e0,1e1,1e2,1e3])
ax2.xaxis.set_ticklabels(("1","10","100","1000"), visible = True)
plt.setp(ax2.get_xticklabels(), visible = True)
colors = ['y','c']
ax1.hist([tips['total_bill'],tips['total_bill']],bins = 10,
stacked=True, color = colors, ec='black')
ax2.hist([tips['tip'],tips['tip']],bins = 10,orientation = 'horizontal',
stacked=True, color = colors, ec='black')
ax2.set_ylabel('')
graph_joint_histograms(tips)
plt.show()

Plot multiple lines with matplotlib, using only 3 lists/arrays

I would like to plot say 10 lines in 3D in matplotlib, but without having to use ax.plot(x,y,z) 10 times.
This is the ridiculous code I've come up with b/c I can't envision how the zip and arrays actually work together.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = np.array([0.,3.])
y = np.array([0.,0.])
z = np.array([0.,0.])
u = np.array([0.,3.])
v = np.array([.5,.5])
w = np.array([0.,0.])
a = np.array([0.,3.])
b = np.array([1.,1.])
c = np.array([0.,0.])
e = np.array([0.,3.])
d = np.array([1.5,1.5])
f = np.array([0.,0.])
r = np.array([0.,3.])
s = np.array([2.,2.])
t = np.array([0.,0.])
ax.set_xlabel("x axis")
ax.set_ylabel("y axis")
ax.set_zlabel("z axis")
ax.plot(x,y,z)
ax.plot(a,b,c)
ax.plot(r,s,t)
ax.plot(u,v,w)
ax.plot(e,d,f)
plt.show()
I'm guessing I'll use zip and/or a for loop.
Thanks, and here's the figure.
You could store all your data points in a large data array. This way you can loop over the array and do something like this:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# initialize array with size number of lines
data = np.full((2,3), None)
# fill data array with data points [x,y,z]
data[0] = [[0,3],[0,0],[0,0]]
data[1] = [[0,3],[0.5,0.5],[0,0]]
# etc...
# loop over data array and plot lines
for line in data:
ax.plot(line[0],line[1],line[2])
plt.show()
There are many different ways on how to store your data, you could also skip the initialization step by just creating the array in one take:
data = np.array([[[0,3],[0,0],[0,0]],
[[0,3],[0.5,0.5],[0,0]],
[[0,3],[0.5,0.5],[0,0]],
[...] ])
Or use numpy functions like numpy.concatenate to add new lines to the data array.

Using plot_date change node icon type

When using plot_date, how do you change some of the nodes in the set from a circle to an X?
For example all nodes are circles except the 3, 8, and 19 node, which are all Xs.
I have used a sample dataset, since you didnt provided any.
import pandas as pd
import matplotlib.pyplot as plt
data = {'2014-11-15':1, '2014-11-16':2, '2014-11-17':3, '2014-11-18':5, '2014-11-19':8, '2014-11-20': 19}
df = pd.DataFrame(list(data.iteritems()), columns=['Date', 'val'])
df = df.set_index(pd.to_datetime(df.Date, format='%Y-%m-%d'))
o_list = []
x_list = []
check_list = [3,8,19]
for index in df.index:
if df.val[index] in check_list:
o_list.append(index)
else:
x_list.append(index)
df_o = df.ix[o_list]
df_x = df.ix[x_list]
fig = plt.figure()
plt.plot_date(df_o.index, df_o.val, 'bo')
plt.plot_date(df_x.index, df_x.val, 'bx')
plt.show()