问题
l would like to plot histograms of three vectors sharing the same x-axis which is classes. Classes (101 string values) is a set of labels
classes={'playingguitar', 'billiards', 'boxingboxingspeedbag', 'applylipstick', 'playingsitar', 'fieldhockeypenalty', 'blowingcandles', 'longjump', 'playingdhol', 'biking', 'playingpiano', 'handstandwalking', 'playingcello', 'ropeclimbing', 'hulahoop', 'cricketshot', 'punch', 'pushups', 'floorgymnastics', 'jumpingjack', 'lunges', 'golfswing', 'bandmarching', 'skiing', 'playingtabla', 'archery', 'breaststroke', 'unevenbars', 'playingviolin', 'babycrawling', 'moppingfloor', 'bowling', 'knitting', 'rockclimbingindoor', 'shavingbeard', 'writingonboard', 'shotput', 'stillrings', 'drumming', 'applyeyemakeup', 'cuttinginkitchen', 'pizzatossing', 'soccerpenalty', 'bodyweightsquats', 'taichi', 'benchpress', 'trampolinejumping', 'playingdaf', 'pullups', 'pommelhorse', 'jumprope', 'headmassage', 'horserace', 'skijet', 'surfing', 'basketballdunk', 'polevault', 'brushingteeth', 'salsaspin', 'frontcrawl', 'horseriding', 'typing', 'throwdiscus', 'nunchucks', 'diving', 'balancebeam', 'highjump', 'volleyballspiking', 'icedancing', 'cricketbowling', 'rafting', 'yoyo', 'walkingwithdog', 'swing', 'hammering', 'mixing', 'wallpushups', 'parallelbars', 'skateboarding', 'skydiving', 'jugglingballs', 'soccerjuggling', 'kayaking', 'cleanandjerk', 'tennisswing', 'playingflute', 'javelinthrow', 'haircut', 'blowdryhair', 'cliffdiving', 'frisbeecatch', 'boxingspeedbag', 'handstandpushups', 'militaryparade', 'hammerthrow', 'rowing', 'basketball', 'baseballpitch', 'tabletennisshot', 'fencing', 'sumowrestling'}
len(classes)=101
In labels2
, labels2_test
, labels2_full_train
we have the number of occurence of each class in different order :
from collections import Counter
import numpy as np
import matplotlib.pyplot as plt
import pylab
labels2, values2 = zip(*Counter(train2).items())
labels2_test, values_test2 = zip(*Counter(test).items())
labels2_full_train, values2_full_train = zip(*Counter(full_train).items())
l would like to make a plot such that x-axis represents classes and y-axis number of occurrence of each class in values2, values_test2, values2_full_train
What l have tried ?
pylab.rcParams['figure.figsize'] = (30, 10)
fig1, ax1 = plt.subplots()
ax1.tick_params(rotation=90)
ax1.plot(labels2, values2, label='train classes')
ax1.plot(labels2_test, values_test2, label='test classes')
ax1.plot(labels2_full_train, values2_full_train, label='test classes')
ax1.set_xlabel("classes",rotation='vertical')
ax1.set_ylabel("number of examples")
ax1.set_title("data distibution")
ax1.legend(loc='best')
fig1.show()
However l get something as follow :
since labels2
, labels2_test
, labels2_full_train
are not ordered in the same way in
labels2, values2 = zip(*Counter(train2).items())
labels2_test, values_test2 = zip(*Counter(test).items())
labels2_full_train, values2_full_train = zip(*Counter(full_train).items())
So how can l get labels2
, labels2_test
, labels2_full_train
in the same order (for instance as defined in classes) ?
For instance
labels2=['rafting', 'punch', 'applyeyemakeup',...]
values2=[78, 112, 106,...]
labels2_test=['typing', 'surfing', 'cricketbowling',..]
values_test2=[46, 38, 39,...]
labels2_full_train=['archery', 'benchpress', 'brushingteeth',...]
values2_full_train=[1046, 1043, 1065,...]
thank you
回答1:
The problem
Because matplotlib shows categorical variables sorted on the axes, you need to sort the lists alphabetically before plotting. So let's create a complete and verifiable example:
from collections import Counter
list1 = list("ABADEAABEDDAEDBBBBBD") # letters A, B, D, E
list2 = list("AABAEEDCCFFFEDABEEC") # all letters A-F
items1, counts1 = zip(*sorted(Counter(list1).items()))
items2, counts2 = zip(*sorted(Counter(list2).items()))
import matplotlib.pyplot as plt
plt.plot(items1, counts1, label="list1")
plt.plot(items2, counts2, label="list2")
plt.legend()
plt.show()
Note that the first list contains a subset of the all possible items. The output looks like this:
So unfortunately, although the lists themselves are sorted, the plot shows some strange behaviour in that the axes shows C
and F
at the end.
The solution
The solution to this would be to let the axis know about all possible items to plot beforehands. We could e.g. plot an invisible plot of all items to the axes,
import matplotlib.pyplot as plt
plt.plot(items1+items2, [5]*len(items1+items2), visible=False)
plt.plot(items1, counts1, "o-", label="list1")
plt.plot(items2, counts2, "o-", label="list2")
plt.legend()
plt.show()
来源:https://stackoverflow.com/questions/48705767/make-3-histograms-in-the-same-figure-by-ordering-x-axis-values