Make 3 histograms in the same figure by ordering x-axis values

泄露秘密 提交于 2019-12-24 10:12:56

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!