0

I have a plot that shows Cumulative Distribution values and a 'survival function' as well.

import numpy as np
import matplotlib.pyplot as plt
values, base = np.histogram(serWEB, bins=100)
cumulative = np.cumsum(values)
# plot the cumulative function
plt.plot(base[:-1], cumulative, c='blue')
plt.title('Cumulative Distribution')
plt.xlabel('X Data')
plt.ylabel('Y Data')
# survival function next  
plt.plot(base[:-1], len(serWEB)-cumulative, c='green')
plt.show()

This plot shows the values as the main Y-Axis. I am interested in adding a 2nd Y-Axis on the right to show the percentages.

How to do that?

Mark Ginsburg
  • 2,139
  • 4
  • 17
  • 31

3 Answers3

2

Using a combination of matplotlib.axes.Axes.twinx and matplotlib.ticker.Formatter should do what you need. First get the current axis, then create a "twin" of it using twinx():

import matplotlib.ticker as mtick
...
ax = plt.gca()  # returns the current axes
ax = ax.twinx() # create twin xaxis
ax.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))

There are quite a few ways you can format the percentage:

PercentFormatter() accepts three arguments, max, decimals, symbol. max allows you to set the value that corresponds to 100% on the axis. This is nice if you have data from 0.0 to 1.0 and you want to display it from 0% to 100%. Just do PercentFormatter(1.0).

The other two parameters allow you to set the number of digits after the decimal point and the symbol. They default to None and '%', respectively. decimals=None will automatically set the number of decimal points based on how much of the axes you are showing.[1]

l'L'l
  • 44,951
  • 10
  • 95
  • 146
  • What I want to accomplish is to have the values on Y-Axis #1 and then the relative percentages on Y-Axis #2. The solution above just converted a raw value of e.g. 150 to "15000 %" on Y-Axis 2. I am looking for the ratio of 150/total # (a percent) to be Y-Axis 2. – Mark Ginsburg Mar 29 '18 at 17:52
  • @MarkGinsburg: I'm not sure what your total is, so I can't really compare anything. Basically all you really should need to do is adjust the number in `PercentFormatter()`, for example you could input (150) or (150/total), etc. (whatever numbers you need to adjust it). Maybe upload some data that can be applied to the graph, that would at least give us an idea what you are expecting. – l'L'l Mar 29 '18 at 18:11
  • In a typical cumulative distribution curve, the Y-Axis scales from 0 to 1 and represents from 0% to 100% of the population. In another variation, instead of 0 to 1, the values are shown on the Y-Axis. I would like to combine them. I want the values on the left, and I want the 0 to 1 scaling on the right. Example of the ratio on the left: https://matplotlib.org/examples/statistics/histogram_demo_cumulative.html – Mark Ginsburg Mar 29 '18 at 18:28
  • @MarkGinsburg: [Here's an example of what the code in my answer along with yours produces](https://i.imgur.com/wBXJakW.png), although maybe I'm missing something here perhaps. – l'L'l Mar 29 '18 at 19:22
0

Check out ax.twinx(), as used e.g. in this question and its answers.

Try this approach:

ax = plt.gca()  # get current active axis
ax2 = ax.twinx()
ax2.plot(base[:-1], (len(serWEB)-cumulative)/len(serWEB), 'r')
Peter Leimbigler
  • 10,775
  • 1
  • 23
  • 37
0

Here is the basic shell of plotting values on the left Y-Axis and ratio on the right Y-Axis (ax2). I used the twinx() function as per the comments.

import numpy as np
import matplotlib.pyplot as plt
# evaluate the histogram
import matplotlib.ticker as mtick 
values, base = np.histogram(serWEB, bins=100)
#evaluate the cumulative
cumulative = np.cumsum(values)
# plot the cumulative function
plt.plot(base[:-1], cumulative, c='blue')
plt.title('Chart Title')
plt.xlabel('X Label')
plt.ylabel('Y Label')
#plot the survival function
plt.plot(base[:-1], len(serWEB)-cumulative, c='green')
# clone the Y-axis and make a Y-Axis #2
ax = plt.gca() 
ax2  = ax.twinx() 
# on the second Y-Axis, plot the ratio from 0 to 1 
n, bins, patches = ax2.hist(serWEB, 100, normed=True, histtype='step', 
cumulative=True)
plt.xticks(np.arange(0,900, step = 14))
plt.xlim(0, 200) 
plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
Mark Ginsburg
  • 2,139
  • 4
  • 17
  • 31
  • Here is the basic shell of plotting values on the left Y-Axis and ratio on the right Y-Axis (ax2). I used the twinx() function as per the comments. – Mark Ginsburg Mar 29 '18 at 18:46