Skip to content

Commit 2f90d6c

Browse files
committed
scale_fill_*. other stuff too.
1 parent e678e6b commit 2f90d6c

12 files changed

+581
-114
lines changed

README.rst

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,6 @@ You can do cool things like this:
2222
.. figure:: ./docs/example.png
2323
:alt:
2424

25-
What happened to the old version that didn't work?
26-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27-
28-
It's gone--the windows, the doors,
29-
`everything <https://www.youtube.com/watch?v=YuxCKv_0GZc>`__. I deleted
30-
most of the code and only kept what worked. The data grouping and
31-
manipulation bits were re-written (so they actually worked) with things
32-
like facets in mind.
33-
34-
Where did ``stat_identity`` and ``geom_raster`` go?
35-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
36-
37-
They're gone. They didn't even come close to working (also what does
38-
``stat_identity`` even do) so they're gone.
39-
4025
Installation
4126
~~~~~~~~~~~~
4227

@@ -54,3 +39,17 @@ Examples
5439
- `gallery <./docs/Gallery.ipynb>`__
5540
- `various examples <./examples.md>`__
5641

42+
What happened to the old version that didn't work?
43+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
44+
45+
It's gone--the windows, the doors,
46+
`everything <https://www.youtube.com/watch?v=YuxCKv_0GZc>`__. I deleted
47+
most of the code and only kept what worked. The data grouping and
48+
manipulation bits were re-written (so they actually worked) with things
49+
like facets in mind.
50+
51+
Where did ``stat_identity`` and ``geom_raster`` go?
52+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53+
54+
They're gone. They didn't even come close to working (also what does
55+
``stat_identity`` even do) so they're gone.

ggplot/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ def _set_mpl_backend():
3939
from .scales.scale_color_funfetti import scale_color_funfetti
4040
from .scales.scale_color_manual import scale_color_manual
4141
from .scales.scale_color_gradient import scale_color_gradient
42+
43+
from .scales.scale_fill_brewer import scale_fill_brewer
44+
from .scales.scale_fill_crayon import scale_fill_crayon
45+
from .scales.scale_fill_funfetti import scale_fill_funfetti
46+
from .scales.scale_fill_manual import scale_fill_manual
47+
4248
from .scales.scale_identity import scale_alpha_identity, scale_color_identity, scale_fill_identity, scale_linetype_identity, scale_shape_identity, scale_size_identity
4349
from .scales.scale_log import scale_x_log, scale_y_log
4450
from .scales.scale_reverse import scale_x_reverse, scale_y_reverse

ggplot/geoms/geom_bar.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ def plot(self, ax, data, _aes, x_levels, fill_levels, lookups):
5757

5858
params = self._get_plot_args(data, _aes)
5959

60-
if self.params.get('position')=='fill':
61-
pass
62-
6360
if fill_levels is not None:
6461
width = .8 / len(fill_levels)
6562
else:

ggplot/ggplot.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,15 @@
1010
import numpy as np
1111
import pandas as pd
1212
import warnings
13-
import itertools
1413

1514
from .aes import aes
1615
from .legend import make_legend
1716
from .themes import theme_gray
1817
from . import discretemappers
1918

20-
import pprint as pp
2119
from PIL import Image
2220

2321

24-
2522
class ggplot(object):
2623
"""
2724
ggplot is the base layer or object that you use to define
@@ -95,17 +92,20 @@ def __init__(self, aesthetics, data):
9592
self.colormap = None
9693
self.manual_color_list = []
9794

95+
# fill (pretty much t, colors=self.manual_fill_listhe same as colors)
96+
self.manual_fill_list = []
97+
9898
# coordinate system
9999
self.coords = None
100100

101101

102102
def __repr__(self):
103103
self.make()
104104
# this is nice for dev but not the best for "real"
105-
# self.fig.savefig('/tmp/ggplot.png', dpi=160)
106-
# img = Image.open('/tmp/ggplot.png')
107-
# img.show()
108-
plt.show()
105+
self.fig.savefig('/tmp/ggplot.png', dpi=160)
106+
img = Image.open('/tmp/ggplot.png')
107+
img.show()
108+
# plt.show()
109109
return "<ggplot: (%d)>" % self.__hash__()
110110

111111
def _evaluate_aes_expressions(self):
@@ -290,7 +290,7 @@ def _get_mapping(self, aes_type, colname):
290290
if aes_type=="color":
291291
mapping = discretemappers.color_gen(self.data[colname].nunique(), colors=self.manual_color_list)
292292
elif aes_type=="fill":
293-
mapping = discretemappers.color_gen(self.data[colname].nunique())
293+
mapping = discretemappers.color_gen(self.data[colname].nunique(), colors=self.manual_fill_list)
294294
elif aes_type=="shape":
295295
mapping = discretemappers.shape_gen()
296296
elif aes_type=="linetype":

ggplot/legend.py

Lines changed: 31 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ def color_legend(color):
3030
# TODO: need outline on line
3131
return plt.Line2D([0],[0], color=color, linewidth=5)
3232

33-
# TODO(bug): this *sometimes* decides to not use marker='o'
3433
def size_legend(size):
3534
return plt.Line2D([0],[0], color='black', marker='o', linestyle='None', markersize=size**.5)
3635

@@ -43,98 +42,45 @@ def shape_legend(shape):
4342
def linetype_legend(linetype):
4443
return plt.Line2D([0],[0], color='black', linestyle=linetype)
4544

45+
def make_aesthetic_legend(aesthetic, value):
46+
if aesthetic=='color':
47+
return color_legend(value)
48+
elif aesthetic=='fill':
49+
return color_legend(value)
50+
elif aesthetic=='size':
51+
return size_legend(value)
52+
elif aesthetic=='alpha':
53+
return alpha_legend(value)
54+
elif aesthetic=='shape':
55+
return shape_legend(value)
56+
elif aesthetic=='linetype':
57+
return linetype_legend(value)
58+
else:
59+
print(aesthetic + " not found")
4660

4761
def make_legend(ax, legend_mapping):
4862
# TODO: for some reason this reaks havoc! but this is also how you would do a bold legend :(
4963
# plt.rc('text', usetex=True)
50-
64+
5165
extra = Rectangle((0, 0), 0, 0, facecolor="w", fill=False, edgecolor='none', linewidth=0)
5266

5367
items = []
5468
labels = []
5569

56-
if 'color' in legend_mapping:
57-
items.append(extra)
58-
colname = legend_mapping['color']['name']
59-
# spacer = r'\n' if len(labels) > 0 else r''
60-
spacer = '\n' if len(labels) > 0 else ''
61-
# TODO: this is supposed to make the label bold
62-
# labels.append(spacer + r'\textbf{' + colname + '}')
63-
labels.append(spacer + colname)
64-
for key in sorted(legend_mapping['color']['lookup'].keys()):
65-
value = legend_mapping['color']['lookup'][key]
66-
legend_item = color_legend(value)
67-
items.append(legend_item)
68-
labels.append(key)
69-
70-
if 'fill' in legend_mapping:
71-
items.append(extra)
72-
colname = legend_mapping['fill']['name']
73-
# spacer = r'\n' if len(labels) > 0 else r''
74-
spacer = '\n' if len(labels) > 0 else ''
75-
# TODO: this is supposed to make the label bold
76-
# labels.append(spacer + r'\textbf{' + colname + '}')
77-
labels.append(spacer + colname)
78-
for key in sorted(legend_mapping['fill']['lookup'].keys()):
79-
value = legend_mapping['fill']['lookup'][key]
80-
legend_item = color_legend(value)
81-
items.append(legend_item)
82-
labels.append(key)
83-
84-
if 'shape' in legend_mapping:
85-
items.append(extra)
86-
colname = legend_mapping['shape']['name']
87-
# spacer = r'\n' if len(labels) > 0 else r''
88-
spacer = '\n' if len(labels) > 0 else ''
89-
# TODO: this is supposed to make the label bold
90-
# labels.append(spacer + r'\textbf{' + colname + '}')
91-
labels.append(spacer + colname)
92-
for key in sorted(legend_mapping['shape']['lookup'].keys()):
93-
value = legend_mapping['shape']['lookup'][key]
94-
legend_item = shape_legend(value)
95-
items.append(legend_item)
96-
labels.append(key)
97-
98-
if 'alpha' in legend_mapping:
99-
items.append(extra)
100-
colname = legend_mapping['alpha']['name']
101-
# spacer = r'\n' if len(labels) > 0 else r''
102-
spacer = '\n' if len(labels) > 0 else ''
103-
# TODO: this is supposed to make the label bold
104-
# labels.append(spacer + r'\textbf{' + colname + '}')
105-
labels.append(spacer + colname)
106-
for key in sorted(legend_mapping['alpha']['lookup'].keys()):
107-
value = legend_mapping['alpha']['lookup'][key]
108-
legend_item = alpha_legend(value)
109-
items.append(legend_item)
110-
labels.append(key)
111-
112-
if 'size' in legend_mapping:
113-
items.append(extra)
114-
colname = legend_mapping['size']['name']
115-
# spacer = r'\n' if len(labels) > 0 else r''
116-
spacer = '\n' if len(labels) > 0 else ''
117-
# TODO: this is supposed to make the label bold
118-
# labels.append(spacer + r'\textbf{' + colname + '}')
119-
labels.append(spacer + colname)
120-
for key in sorted(legend_mapping['size']['lookup'].keys()):
121-
value = legend_mapping['size']['lookup'][key]
122-
legend_item = size_legend(value)
123-
items.append(legend_item)
124-
labels.append(key)
125-
126-
if 'linetype' in legend_mapping:
127-
items.append(extra)
128-
colname = legend_mapping['linetype']['name']
129-
# spacer = r'\n' if len(labels) > 0 else r''
130-
spacer = '\n' if len(labels) > 0 else ''
131-
# TODO: this is supposed to make the label bold
132-
# labels.append(spacer + r'\textbf{' + colname + '}')
133-
labels.append(spacer + colname)
134-
for key in sorted(legend_mapping['linetype']['lookup'].keys()):
135-
value = legend_mapping['linetype']['lookup'][key]
136-
legend_item = linetype_legend(value)
137-
items.append(legend_item)
138-
labels.append(key)
70+
for aesthetic in ['color', 'fill', 'shape', 'alpha', 'size', 'linetype']:
71+
72+
if aesthetic in legend_mapping:
73+
items.append(extra)
74+
colname = legend_mapping[aesthetic]['name']
75+
# spacer = r'\n' if len(labels) > 0 else r''
76+
spacer = '\n' if len(labels) > 0 else ''
77+
# TODO: this is supposed to make the label bold
78+
# labels.append(spacer + r'\textbf{' + colname + '}')
79+
labels.append(spacer + colname)
80+
for key in sorted(legend_mapping[aesthetic]['lookup'].keys()):
81+
value = legend_mapping[aesthetic]['lookup'][key]
82+
legend_item = make_aesthetic_legend(aesthetic, value)
83+
items.append(legend_item)
84+
labels.append(key)
13985

14086
legend = ax.legend(items, labels, loc='center left', bbox_to_anchor=(1.05, 0.5), fontsize='small', frameon=False)

ggplot/scales/scale_fill_brewer.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from __future__ import (absolute_import, division, print_function,
2+
unicode_literals)
3+
from .scale import scale
4+
from copy import deepcopy
5+
import brewer2mpl
6+
7+
8+
def _number_to_palette(ctype, n):
9+
n -= 1
10+
palettes = sorted(brewer2mpl.COLOR_MAPS[ctype].keys())
11+
if n < len(palettes):
12+
return palettes[n]
13+
14+
def _handle_shorthand(text):
15+
abbrevs = {
16+
"seq": "Sequential",
17+
"qual": "Qualitative",
18+
"div": "Diverging"
19+
}
20+
text = abbrevs.get(text, text)
21+
text = text.title()
22+
return text
23+
24+
class scale_fill_brewer(scale):
25+
"""
26+
Parameters
27+
----------
28+
type: string
29+
One of seq (sequential), div (diverging) or qual (qualitative)
30+
palette: string
31+
If a string, will use that named palette. If a number, will index into
32+
the list of palettes of appropriate type
33+
34+
Examples
35+
--------
36+
>>> from ggplot import *
37+
>>> p = ggplot(aes(x='price', fill='clarity'), data=diamonds)
38+
>>> p += geom_bar()
39+
>>> print(p + scale_fill_brewer(palette=4))
40+
>>> print(p + scale_fill_brewer(type='diverging'))
41+
>>> print(p + scale_fill_brewer(type='div'))
42+
>>> print(p + scale_fill_brewer(type='seq'))
43+
>>> print(p + scale_fill_brewer(type='seq', palette='Blues'))
44+
"""
45+
VALID_SCALES = ['type', 'palette']
46+
47+
def __radd__(self, gg):
48+
# gg = deepcopy(gg)
49+
50+
if self.type:
51+
ctype = self.type
52+
else:
53+
ctype = "Sequential"
54+
55+
ctype = _handle_shorthand(ctype)
56+
57+
if self.palette:
58+
palette = self.palette
59+
else:
60+
palette = _number_to_palette(ctype, 1)
61+
62+
if isinstance(palette, int):
63+
palette = _number_to_palette(ctype, palette)
64+
65+
# color brewer requires a minimum of 3 colors in a palette
66+
try:
67+
fill_col = gg._aes.data.get('fill')
68+
n_colors = max(gg.data[color_col].nunique(), 3)
69+
except:
70+
# If we are neither using 'color' nor 'fill' then assume there is
71+
# only one color used
72+
n_colors = 3
73+
74+
bmap = brewer2mpl.get_map(palette, ctype, n_colors)
75+
gg.manual_fill_list = bmap.hex_colors
76+
77+
return gg

0 commit comments

Comments
 (0)