I'm trying to do something pretty simple, but I'm a novice Python user so this has proven a little difficult for me. I'm trying to make pie charts and the labels for the charts are appearing for the wrong slices of pie.
Here is my code:
import matplotlib.pyplot as plt
# Data to plot
labels = data['Category'].unique()
sizes = (data['Category'].value_counts()/data['Category'].value_counts().sum())*100
# Plot
plt.pie(sizes, labels=labels,
autopct='%1.1f%%', shadow=True, startangle=140)
plt.axis('equal')
plt.legend(labels, loc="best")
plt.tight_layout()
plt.show()
This code produces a pie chart, but the labels in the legend do not match the labels on the chart. I've identified that this is due to the order with which the values of 'Category' appear in the data differ from the order of the values in the line where I define "sizes".
Does anyone know how to sync sizes and labels so the appropriate label is shown on the pie chart?
Any help would be appreciated! Thank you!
You can use labels = sizes.index so both will have the same order. If you want the labels sorted, you could first call sizes = sizes.sort_index(). Or, to have them sorted by value: sizes = sizes.sort_values(). Default, they would be sorted in order of appearance.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
data = pd.DataFrame({'Category': np.random.choice(list('abcdefghij'), 500)})
sizes = data['Category'].value_counts().sort_index() / data['Category'].value_counts().sum() * 100
plt.pie(sizes, labels=sizes.index,
autopct='%1.1f%%', shadow=True, startangle=140)
plt.axis('equal')
plt.legend(sizes.index, loc="best")
plt.tight_layout()
plt.show()
Related
I am creating shot plots for NHL games and I have succeeded in making the plot, but I would like to draw the lines that you see on a hockey rink on it. I basically just want to draw two circles and two lines on the plot like this.
Let me know if this is possible/how I could do it
Pandas plot is in fact matplotlib plot, you can assign it to variable and modify it according to your needs ( add horizontal and vertical lines or shapes, text, etc)
# plot your data, but instead diplaying it assing Figure and Axis to variables
fig, ax = df.plot()
ax.vlines(x, ymin, ymax, colors='k', linestyles='solid') # adjust to your needs
plt.show()
working code sample
import pandas as pd
import matplotlib.pyplot as plt
import seaborn
from matplotlib.patches import Circle
from matplotlib.collections import PatchCollection
df = seaborn.load_dataset('tips')
ax = df.plot.scatter(x='total_bill', y='tip')
ax.vlines(x=40, ymin=0, ymax=20, colors='red')
patches = [Circle((50,10), radius=3)]
collection = PatchCollection(patches, alpha=0.4)
ax.add_collection(collection)
plt.show()
I am trying to plot multiple rgb images with matplotlib
the code I am using is:
import numpy as np
import matplotlib.pyplot as plt
for i in range(0, images):
test = np.random.rand(1080, 720,3)
plt.subplot(images,2,i+1)
plt.imshow(test, interpolation='none')
the subplots appear tiny though as thumbnails
How can I make them bigger?
I have seen solutions using
fig, ax = plt.subplots()
syntax before but not with plt.subplot ?
plt.subplots initiates a subplot grid, while plt.subplot adds a subplot. So the difference is whether you want to initiate you plot right away or fill it over time. Since it seems, that you know how many images to plot beforehand, I would also recommend going with subplots.
Also notice, that the way you use plt.subplot you generate empy subplots in between the ones you are actually using, which is another reason they are so small.
import numpy as np
import matplotlib.pyplot as plt
images = 4
fig, axes = plt.subplots(images, 1, # Puts subplots in the axes variable
figsize=(4, 10), # Use figsize to set the size of the whole plot
dpi=200, # Further refine size with dpi setting
tight_layout=True) # Makes enough room between plots for labels
for i, ax in enumerate(axes):
y = np.random.randn(512, 512)
ax.imshow(y)
ax.set_title(str(i), fontweight='bold')
I faced a serious problem when I was trying to add colorbar to scatter plot which indicates in which classes individual sample belongs to. The code works perfectly when classes are [0,1,2] but when the classes are for example [4,5,6] chooses colorbar automatically color values in the end of colormap and colorbar looks blue solid color. I'm missing something obvious but I just can't figure out what it is.
Here is the example code about the problem:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(1 , figsize=(6, 6))
plt.scatter(datapoints[:,0], datapoints[:,1], s=20, c=labels, cmap='jet', alpha=1.0)
plt.setp(ax, xticks=[], yticks=[])
cbar = plt.colorbar(boundaries=np.arange(len(classes)+1)-0.5)
cbar.set_ticks(np.arange(len(classes)))
cbar.set_ticklabels(classes)
plt.show()
Variables can be for example
datapoints = np.array([[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7]])
labels = np.array([4,5,6,4,5,6,4])
classes = np.array([4,5,6])
Correct result is got when
labels = np.array([0,1,2,0,1,2,0])
In my case I want it to work also for classes [4,5,6]
The buoundaries need to be in data units. Meaning, if your classes are 4,5,6, you probably want to use boundaries of 3.5, 4.5, 5.5, 6.5.
import matplotlib.pyplot as plt
import numpy as np
datapoints = np.array([[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7]])
labels = np.array([4,5,6,4,5,6,4])
classes = np.array([4,5,6])
fig, ax = plt.subplots(1 , figsize=(6, 6))
sc = ax.scatter(datapoints[:,0], datapoints[:,1], s=20, c=labels, cmap='jet', alpha=1.0)
ax.set(xticks=[], yticks=[])
cbar = plt.colorbar(sc, ticks=classes, boundaries=np.arange(4,8)-0.5)
plt.show()
If you wanted to have the boundaries determined automatically from the classes, some assumption must me made. E.g. if all classes are subsequent integers,
boundaries=np.arange(classes.min(), classes.max()+2)-0.5
In general, an alternative would be to use a BoundaryNorm, as shown e.g. in Create a discrete colorbar in matplotlib
or How to specify different color for a specific year value range in a single figure? (Python) or python colormap quantisation (matplotlib)
I'm trying to visualize what filters are learning in CNN text classification model. To do this, I extracted feature maps of text samples right after the convolutional layer, and for size 3 filter, I got an (filter_num)*(length_of_sentences) sized tensor.
df = pd.DataFrame(-np.random.randn(50,50), index = range(50), columns= range(50))
g= sns.clustermap(df,row_cluster=True,col_cluster=False)
plt.setp(g.ax_heatmap.yaxis.get_majorticklabels(), rotation=0) # ytick rotate
g.cax.remove() # remove colorbar
plt.show()
This code results in :
Where I can't see all the ticks in the y-axis. This is necessary
because I need to see which filters learn which information. Is there
any way to properly exhibit all the ticks in the y-axis?
kwargs from sns.clustermap get passed on to sns.heatmap, which has an option yticklabels, whose documentation states (emphasis mine):
If True, plot the column names of the dataframe. If False, don’t plot the column names. If list-like, plot these alternate labels as the xticklabels. If an integer, use the column names but plot only every n label. If “auto”, try to densely plot non-overlapping labels.
Here, the easiest option is to set it to an integer, so it will plot every n labels. We want every label, so we want to set it to 1, i.e.:
g = sns.clustermap(df, row_cluster=True, col_cluster=False, yticklabels=1)
In your complete example:
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.DataFrame(-np.random.randn(50,50), index=range(50), columns=range(50))
g = sns.clustermap(df, row_cluster=True, col_cluster=False, yticklabels=1)
plt.setp(g.ax_heatmap.yaxis.get_majorticklabels(), rotation=0) # ytick rotate
g.cax.remove() # remove colorbar
plt.show()
How would you go about changing the style of only some boxes in a matplotlib boxplot? Below, you can see an example of styling, but I would like the style to only apply to one of the boxes.
The same question has been asked for seaborn boxplots already. For matplotlib boxplots this is even easier, since the boxplot directly returns a dictionary of the involved artists, see boxplot documentation.
This means that if bplot = ax.boxplot(..) is your boxplot, you may access the boxes via bplot['boxes'], select one of them and set its linestyle to your desire. E.g.
bplot['boxes'][2].set_linestyle("-.")
Modifying the boxplot_color example
import matplotlib.pyplot as plt
import numpy as np
# Random test data
np.random.seed(19680801)
all_data = [np.random.normal(0, std, size=100) for std in range(1, 4)]
labels = ['x1', 'x2', 'x3']
fig, ax = plt.subplots()
# notch shape box plot
bplot = ax.boxplot(all_data, vert=True, patch_artist=True, labels=labels)
# Loop through boxes and colorize them individually
colors = ['pink', 'lightblue', 'lightgreen']
for patch, color in zip(bplot['boxes'], colors):
patch.set_facecolor(color)
# Make the third box dotted
bplot['boxes'][2].set_linestyle("-.")
plt.show()