Sources I used for parts of this, and other things that might be helpful:
I had trouble finding a default color set with 11 colors for the petroleum data. Eventually discovered Palettable, and am using Paired_11 here. It is not my first choice of a color plot, but is one of the few defaults with that many colors. I generally recommend using one of the default seaborn color palettes such as muted or deep. Check out the seaborn tutorial for a basic primer colors.
In [2]:
%matplotlib inline
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.path as path
from palettable.colorbrewer.qualitative import Paired_11
Data is from:
McGlade, C & Ekins, P. The geographical distribution of fossil fuels unused when limiting global warming to 2 °C. Nature 517, 187–190. (2015) doi:10.1038/nature14016
Coal data from Figure 1c.
In [4]:
fn = 'nature14016-f1.xlsx'
sn = 'Coal data'
In [5]:
coal_df = pd.read_excel(fn, sn)
Fortuntely the Cost values are already sorted in ascending order. Cost will be on the y-axis, and cumulative recoverable resources will be on the x-axis.
In [6]:
coal_df.head()
Out[6]:
In [7]:
coal_df.tail()
Out[7]:
In [20]:
names = coal_df['Resource'].values
amount = coal_df['Quantity (ZJ)'].values
cost = coal_df['Cost (2010$/GJ)'].values
In [21]:
name_set = set(names)
name_set
Out[21]:
In [22]:
color_dict = {}
for i, area in enumerate(name_set):
color_dict[area] = i #Assigning index position as value to resource name keys
In [23]:
color_dict
Out[23]:
In [24]:
sns.color_palette('deep', n_colors=4, desat=.8)
Out[24]:
In [25]:
sns.palplot(sns.color_palette('deep', n_colors=4, desat=.8))
In [26]:
def color_match(name):
return sns.color_palette('deep', n_colors=4, desat=.8)[color_dict[name]]
color
has rgb values for each resource
In [28]:
color = coal_df['Resource'].map(color_match)
In [29]:
color.head()
Out[29]:
In [30]:
# get the corners of the rectangles for the histogram
left = np.cumsum(np.insert(amount, 0, 0))
right = np.cumsum(np.append(amount, .01))
bottom = np.zeros(len(left))
top = np.append(cost, 0)
In [37]:
sns.set_style('whitegrid')
fig, ax = plt.subplots(figsize=(10,5))
# we need a (numrects x numsides x 2) numpy array for the path helper
# function to build a compound path
for i, name in enumerate(names):
XY = np.array([[left[i:i+1], left[i:i+1], right[i:i+1], right[i:i+1]],
[bottom[i:i+1], top[i:i+1], top[i:i+1], bottom[i:i+1]]]).T
# get the Path object
barpath = path.Path.make_compound_path_from_polys(XY)
# make a patch out of it (a patch is the shape drawn on the plot)
patch = patches.PathPatch(barpath, facecolor=color[i], ec='0.2')
ax.add_patch(patch)
#Create patch elements for a custom legend
#The legend function expects multiple patch elements as a list
patch = [patches.Patch(color=sns.color_palette('deep', 4, 0.8)[color_dict[i]], label=i)
for i in color_dict]
# Axis labels/limits, remove horizontal gridlines, etc
plt.ylabel('Cost (2010$/GJ)', size=14)
plt.xlabel('Quantity (ZJ)', size=14)
ax.set_xlim(left[0], right[-1])
ax.set_ylim(bottom.min(), 12)
ax.yaxis.grid(False)
ax.xaxis.grid(False)
#remove top and right spines (box lines around figure)
sns.despine()
#Add the custom legend
plt.legend(handles=patch, loc=2, fontsize=12)
plt.savefig('Example Supply Curve (coal).png')
Data is from:
McGlade, C & Ekins, P. The geographical distribution of fossil fuels unused when limiting global warming to 2 °C. Nature 517, 187–190. (2015) doi:10.1038/nature14016
I'm using data from Figure 1a.
In [11]:
fn = 'nature14016-f1.xlsx'
sn = 'Oil data'
In [12]:
df = pd.read_excel(fn, sn)
Fortuntely the Cost values are already sorted in ascending order. Cost will be on the y-axis, and cumulative recoverable resources will be on the x-axis.
In [13]:
df.head()
Out[13]:
In [14]:
df.tail()
Out[14]:
In [15]:
names = df['Resource'].values
amount = df['Quantity (Gb)'].values
cost = df['Cost (2010$/bbl)'].values
In [16]:
name_set = set(names)
name_set
Out[16]:
In [17]:
color_dict = {}
for i, area in enumerate(name_set):
color_dict[area] = i #Assigning index position as value to resource name keys
In [18]:
color_dict
Out[18]:
In [53]:
sns.palplot(Paired_11.mpl_colors)
In [119]:
def color_match(name):
return Paired_11.mpl_colors[color_dict[name]]
In [102]:
def color_match(name):
return sns.husl_palette(n_colors=11, h=0.1, s=0.9, l=0.6)[color_dict[name]]
In [143]:
color_match('NGL')
Out[143]:
In [120]:
color = df['Resource'].map(color_match)
In [87]:
# get the corners of the rectangles for the histogram
left = np.cumsum(np.insert(amount, 0, 0))
right = np.cumsum(np.append(amount, .01))
bottom = np.zeros(len(left))
top = np.append(cost, 0)
In [145]:
sns.set_style('whitegrid')
fig, ax = plt.subplots(figsize=(10,5))
# we need a (numrects x numsides x 2) numpy array for the path helper
# function to build a compound path
for i, name in enumerate(names):
XY = np.array([[left[i:i+1], left[i:i+1], right[i:i+1], right[i:i+1]],
[bottom[i:i+1], top[i:i+1], top[i:i+1], bottom[i:i+1]]]).T
# get the Path object
barpath = path.Path.make_compound_path_from_polys(XY)
# make a patch out of it (a patch is the shape drawn on the plot)
patch = patches.PathPatch(barpath, facecolor=color[i], ec='0.8')
ax.add_patch(patch)
#Create patch elements for a custom legend
#The legend function expects multiple patch elements as a list
patch = []
for i in color_dict:
patch.append(patches.Patch(color=Paired_11.mpl_colors[color_dict[i]],
label=i))
# Axis labels/limits, remove horizontal gridlines, etc
plt.ylabel('Cost (2010$/bbl)', size=14)
plt.xlabel('Quantity (Gb)', size=14)
ax.set_xlim(left[0], right[-2])
ax.set_ylim(bottom.min(), 120)
ax.yaxis.grid(False)
ax.xaxis.grid(False)
#remove top and right spines (box lines around figure)
sns.despine()
#Add the custom legend
plt.legend(handles=patch, loc=2, fontsize=12,
ncol=2)
plt.savefig('Example Supply Curve.png')
In [ ]: