Related
How to add two sets of arrows with different colours, please? I obtained just green arrows. Are red arrows overplotted? How to suppress that?
When I comment the part between ###, I have red arrows.
The desired result is to have both arrows - red and green.
Thank you
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
d = {'a': [1, 2, 2], 'b': [3, 5, 4], 'c': [0.1, 0.2, 0.6]}
df = pd.DataFrame(data=d)
fig = px.scatter(df, x='a', y='b', error_y='c')
fig.update_xaxes(title_font_family="Trebuchet")
fig.update_layout(yaxis=dict(scaleanchor="x", scaleratio=1),
template = "plotly_white",
title="<b>V</b>",
)
fig.update_layout(xaxis = dict(autorange="reversed"))
x_end = [1, 2, 2]
y_end = [3, 5, 4]
x_start = [0, 1, 3]
y_start = [4, 4, 4]
list_of_all_arrows = []
for x0,y0,x1,y1 in zip(x_end, y_end, x_start, y_start):
arrow = go.layout.Annotation(dict(
x=x0,
y=y0,
xref="x", yref="y",
text="",
showarrow=True,
axref="x", ayref='y',
ax=x1,
ay=y1,
arrowhead=3,
arrowwidth=1.5,
arrowcolor='rgb(255,51,0)',)
)
list_of_all_arrows.append(arrow)
fig.update_layout(annotations=list_of_all_arrows)
###
list_of_all_arrows2 = []
for x0,y0,x1,y1 in zip([i-2 for i in x_end], [i-3 for i in y_end], x_start, y_start):
arrow = go.layout.Annotation(dict(
x=x0,
y=y0,
xref="x", yref="y",
text="",
showarrow=True,
axref="x", ayref='y',
ax=x1,
ay=y1,
arrowhead=3,
arrowwidth=1.5,
arrowcolor='green',)
)
list_of_all_arrows2.append(arrow)
fig.update_layout(annotations=list_of_all_arrows2)
###
# fig.write_html("Fig.html")
fig.show()
The origin of the problem is that in the background figures in plotly are dictionaries. The fact that you are calling two times fig.update_layout(annotations=list_anotation) updates figure's dictionary annotations entry. To check the dictionary of a figure just print the figure print(fig), there you can see the key layout and sub key annotations.
Therefore only calling one the function update_layout works as you want.
Step1: delete this line
fig.update_layout(annotations=list_of_all_arrows) # delete this line
Step2: change last line
fig.update_layout(annotations=list_of_all_arrows2 + list_of_all_arrows)
this is equivalent to appending all arrows to a single list
Total code
import plotly.express as px
import numpy as np
import pandas as pd
import plotly.graph_objects as go
d = {'a': [1, 2, 2], 'b': [3, 5, 4], 'c': [0.1, 0.2, 0.6]}
df = pd.DataFrame(data=d)
fig = px.scatter(df, x='a', y='b', error_y='c')
fig.update_xaxes(title_font_family="Trebuchet")
fig.update_layout(yaxis=dict(scaleanchor="x", scaleratio=1),
template = "plotly_white",
title="<b>V</b>",
)
fig.update_layout(xaxis = dict(autorange="reversed"))
x_end = [1, 2, 2]
y_end = [3, 5, 4]
x_start = [0, 1, 3]
y_start = [4, 4, 4]
list_of_all_arrows = []
for x0,y0,x1,y1 in zip(x_end, y_end, x_start, y_start):
arrow = go.layout.Annotation(dict(
x=x0,
y=y0,
xref="x", yref="y",
text="",
showarrow=True,
axref="x", ayref='y',
ax=x1,
ay=y1,
arrowhead=3,
arrowwidth=1.5,
arrowcolor='rgb(255,51,0)',)
)
list_of_all_arrows.append(arrow)
list_of_all_arrows2 = []
for x0,y0,x1,y1 in zip([i-2 for i in x_end], [i-3 for i in y_end], x_start, y_start):
arrow = go.layout.Annotation(dict(
x=x0,
y=y0,
xref="x", yref="y",
text="",
showarrow=True,
axref="x", ayref='y',
ax=x1,
ay=y1,
arrowhead=3,
arrowwidth=1.5,
arrowcolor='green',)
)
list_of_all_arrows2.append(arrow)
fig.update_layout(annotations=list_of_all_arrows2 + list_of_all_arrows)
The final plot
How to:
display symbols in the legend
colour markers in the same way as the errorbars (argument color gives an error: ValueError: RGBA sequence should have length 3 or 4
remove connecting lines - get only the scatter with errorbars
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D # for legend handle
fig, ax = plt.subplots(figsize = (10,10))
times = [1, 2, 3, 4, 5]
rvs = [2, 4, 2, 4, 7]
sigma = [0.564, 0.6, 0.8, 0.8, 0.4]
rv_telescopes = ['A', 'B', 'A', 'C', 'C']
d = {'rv_times': times, 'rv_rvs': rvs, 'rv_sigma': sigma, 'rv_telescopes': rv_telescopes }
df = pd.DataFrame(data=d)
colors = {'A':'#008f00', 'B':'#e36500', 'C':'red'}
plt.errorbar(df['rv_times'], df['rv_rvs'], df['rv_sigma'], marker = '_', ecolor = df['rv_telescopes'].map(colors), color = df['rv_telescopes'].map(colors), zorder = 1, ms = 30)
handles = [Line2D([0], [0], marker='_', color='w', markerfacecolor=v, label=k, markersize=10) for k, v in colors.items()]
ax.legend(handles=handles, loc='upper left', ncol = 2, fontsize=14)
plt.show()
After edit
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D # for legend handle
import pandas as pd
import numpy as np
times = [1, 2, 3, 4, 5]
rvs = [2, 4, 2, 4, 7]
sigma = [0.564, 0.6, 0.8, 0.8, 0.4]
rv_telescopes = ['A', 'B', 'A', 'C', 'C']
d = {'rv_times': times, 'rv_rvs': rvs, 'rv_sigma': sigma, 'rv_telescopes': rv_telescopes}
df = pd.DataFrame(data=d)
colors = {'A': '#008f00', 'B': '#e36500', 'C': 'red'}
fig, ax = plt.subplots(figsize=(10, 10))
ax.errorbar(df['rv_times'], df['rv_rvs'], df['rv_sigma'], color='none', ecolor=df['rv_telescopes'].map(colors) ,linewidth=1)
ax.scatter(df['rv_times'], df['rv_rvs'], marker='_', linewidth=3, color=df['rv_telescopes'].map(colors), s=1000)
for rv_teles in np.unique(df['rv_telescopes']):
color = colors[rv_teles]
df1 = df[df['rv_telescopes'] == rv_teles] # filter out rows corresponding to df['rv_telescopes']
ax.errorbar(df1['rv_times'], df1['rv_rvs'], df1['rv_sigma'],
color=color, ls='', marker='_', ms=30, linewidth=3, label=rv_teles)
ax.legend(loc='upper left', ncol=1, fontsize=14)
plt.show()
plt.errorbar() works very similar to plt.plot() with extra parameters. As such, it primarily draws a line graph, using a single color. The error bars can be given individual colors via the ecolor= parameter. The markers, however, get the same color as the line graph. The line graph can be suppressed via an empty linestyle. On top of that, plt.scatter() can draw markers with individual colors.
In order not the mix the 'object-oriented' with the 'functional interface', the following example code uses ax.errorbar() and ax.scatter().
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D # for legend handle
import pandas as pd
import numpy as np
times = [1, 2, 3, 4, 5]
rvs = [2, 4, 2, 4, 7]
sigma = [0.564, 0.6, 0.8, 0.8, 0.4]
rv_telescopes = ['A', 'B', 'A', 'C', 'C']
d = {'rv_times': times, 'rv_rvs': rvs, 'rv_sigma': sigma, 'rv_telescopes': rv_telescopes}
df = pd.DataFrame(data=d)
colors = {'A': '#008f00', 'B': '#e36500', 'C': 'red'}
fig, ax = plt.subplots(figsize=(10, 10))
ax.errorbar(df['rv_times'], df['rv_rvs'], df['rv_sigma'], color='none', ecolor=df['rv_telescopes'].map(colors))
ax.scatter(df['rv_times'], df['rv_rvs'], marker='_', color=df['rv_telescopes'].map(colors), s=100)
handles = [Line2D([0], [0], linestyle='', marker='_', color=v, label=k, markersize=10) for k, v in colors.items()]
ax.legend(handles=handles, loc='upper left', ncol=1, fontsize=14)
plt.show()
A far easier approach would be to call ax.errorbar() multiple times, once for each color. This would automatically create appropriate legend handles:
for rv_teles in np.unique(df['rv_telescopes']):
color = colors[rv_teles]
df1 = df[df['rv_telescopes'] == rv_teles] # filter out rows corresponding to df['rv_telescopes']
ax.errorbar(df1['rv_times'], df1['rv_rvs'], df1['rv_sigma'],
color=color, ls='', marker='_', ms=30, label=rv_teles)
ax.legend(loc='upper left', ncol=1, fontsize=14)
plt.show()
I want to generate the annotated heatmap where each column will be having new color.
<my code>
```
import seaborn as sns
import matplotlib.pyplot as plt
df = pd.DataFrame({'clust': ['Clust 10','Clust 11','Clust 1','Clust 2','Clust 10','Clust 11','Clust 1','Clust 2','Clust 10','Clust 11','Clust 1','Clust 2'],'value': [4,2,0,0, 0,0,1,3, 1,0,0,0], 'category': ['A','A','A','A','B','B','B','B','C','C','C','C']})
result = df.pivot(index='clust', columns='category',values='value')
sns.heatmap(result, annot=True, fmt="g", cmap='viridis')
plt.show()
```
<Input file>
No A B C
Clust 10 4 0 1
Clust 11 2 0 0
Clust 1 0 1 0
Clust 2 0 3 0
Clust 3 3 1 0
Clust 4 2 0 2
<Output>
enter image description here
You can create a heat map by plotly module in python. Below is the code which will generate heatmap.
import plotly.figure_factory as ff
a = [
[4, 0, 1],
[2, 0, 0],
[0, 1, 0],
[0, 3, 0],
[3, 1, 0],
[2, 0, 2]
]
fig = ff.create_annotated_heatmap(a)
fig.show()
See https://plot.ly/python/annotated-heatmap/ for more information on how to generate heatmap.
Note: I have not tested it but this code is for reference.
Working code.
```
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
df = pd.DataFrame({'clust': ['Clust 10','Clust 11','Clust 1','Clust 2','Clust 10','Clust 11','Clust 1','Clust 2','Clust 10','Clust 11','Clust 1','Clust 2'],'value': [4,2,0,0, 0,0,1,3, 1,0,0,0], 'category': ['A','A','A','A','B','B','B','B','C','C','C','C']})
result = df.pivot(index='clust', columns='category',values='value')
print(result)
cm = ['Blues', 'Greens', 'YlG']
f, axs = plt.subplots(1, df.columns.size, gridspec_kw={'wspace': 0})
for i, (s, a, c) in enumerate(zip(result.columns, axs, cm)):
sns.heatmap(np.array([result[s].values]).T, yticklabels=result.index, xticklabels=[s], annot=True, fmt='.2f', ax=a, cmap=c, cbar=False)
if i>0:
a.yaxis.set_ticks([])
plt.show()
```
How Can i make this image stretchable using mouse event in matplotlib. please help.
Here the code:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as image
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
fig = plt.figure()
X = [1, 2, 3, 4, 5, 6, 7]
Y = [1, 3, 4, 2, 5, 8, 6]
mainaxes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # main axes
img = image.imread('https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png')
z = 0.3 + 0.3
imagebox = OffsetImage(img, zoom=z)
imgbox = AnnotationBbox(imagebox, (0.3,0.5), frameon=True)
mainaxes.add_artist(imgbox)
imgbox.draggable()
plt.show()
Given the following bar chart:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({'A': ['A', 'B'], 'B': [1000,2000]})
fig, ax = plt.subplots(1, 1, figsize=(2, 2))
df.plot(kind='bar', x='A', y='B',
align='center', width=.5, edgecolor='none',
color='grey', ax=ax)
plt.xticks(rotation=25)
plt.show()
I'd like to display the y-tick labels as thousands of dollars like this:
$2,000
I know I can use this to add a dollar sign:
import matplotlib.ticker as mtick
fmt = '$%.0f'
tick = mtick.FormatStrFormatter(fmt)
ax.yaxis.set_major_formatter(tick)
...and this to add a comma:
ax.get_yaxis().set_major_formatter(
mtick.FuncFormatter(lambda x, p: format(int(x), ',')))
...but how do I get both?
Thanks in advance!
You can use StrMethodFormatter, which uses the str.format() specification mini-language.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
df = pd.DataFrame({'A': ['A', 'B'], 'B': [1000,2000]})
fig, ax = plt.subplots(1, 1, figsize=(2, 2))
df.plot(kind='bar', x='A', y='B',
align='center', width=.5, edgecolor='none',
color='grey', ax=ax)
fmt = '${x:,.0f}'
tick = mtick.StrMethodFormatter(fmt)
ax.yaxis.set_major_formatter(tick)
plt.xticks(rotation=25)
plt.show()
You can also use the get_yticks() to get an array of the values displayed on the y-axis (0, 500, 1000, etc.) and the set_yticklabels() to set the formatted value.
df = pd.DataFrame({'A': ['A', 'B'], 'B': [1000,2000]})
fig, ax = plt.subplots(1, 1, figsize=(2, 2))
df.plot(kind='bar', x='A', y='B', align='center', width=.5, edgecolor='none',
color='grey', ax=ax)
--------------------Added code--------------------------
# getting the array of values of y-axis
ticks = ax.get_yticks()
# formatted the values into strings beginning with dollar sign
new_labels = [f'${int(amt)}' for amt in ticks]
# Set the new labels
ax.set_yticklabels(new_labels)
-------------------------------------------------------
plt.xticks(rotation=25)
plt.show()