Skip to content

Commit

Permalink
getting ready for 2.0 release
Browse files Browse the repository at this point in the history
- added Animator
- added support for pie chart into animator
- added bar1 which is just for showing 1d data
- changed bars() slightly
- removed rotation from corr() labels
- added sort to count()
- many improvements to line()
- some improvements to overlap()
- pie() is more or less redone from ground up
- scat() is cleaned up
- added microseconds to the end of the saved file name string
- title is now produced only if there is input for title (no empty space in some plots)
- changed the way the tick params for timeseries are handled
- added one new exception for the cases where labels are missing
- added function for loading data (just placeholder for now)
- cleaned up and fixed some issues from transforms.py
- added a rational way for sizing of a single seaborn factorplot
- added random color option for colors
- added new 'colorblind' default that support several kinds of colorblindness
- added one more new colorblind palette with 14 colors

LOTS OF TESTING! :)
  • Loading branch information
mikkokotila committed Apr 21, 2018
1 parent 158d17b commit cdc1afc
Show file tree
Hide file tree
Showing 19 changed files with 447 additions and 73 deletions.
6 changes: 5 additions & 1 deletion astetik/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from .plots.multikde import multikde
from .plots.compare import compare
from .plots.multicount import multicount
from .plots.bar1 import bar1
from .plots.animate import Animation
# from .plots.words import words


Expand All @@ -25,4 +27,6 @@
from .tables.text import text
# from .tables.timeseries import timeseries

__version__ = "1.1"
from .utils.transform import boolcols_to_cat

__version__ = "1.9"
60 changes: 60 additions & 0 deletions astetik/plots/animate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import glob
import os
import numpy as np
import matplotlib.pyplot as plt

from IPython.display import clear_output


class Animation():

'''ANIMATED CHARTS
Supports dataformat where x and y are compared against each other, and
label_col provides the title (e.g. year) for each frame in the animation.
y and x are used for the legend labels when relevant.
'''

def __init__(self, data, x, y, label_col, plot_type, filename='animation',
dpi=72, palette='default'):

self.plot_type = plot_type
self.data = data
self.x = x
self.y = y
self.label_col = label_col
self.palette = palette
self.filename = filename
self.frames = len(data)
self.dpi = dpi

# RUNTIME
self._ = self._create_plots()
self._ = self._create_gif()

def _create_plots(self):

for i in range(self.frames):
data = np.array([self.data[self.x][i], self.data[self.y][i]]).astype(int)
self.plot_type(data,
labels=[self.x, self.y],
palette=self.palette,
sub_title=self.data[self.label_col][i],
save=True,
dpi=self.dpi)
clear_output()
plt.show()

def _create_gif(self):

gif_name = self.filename
file_list = glob.glob('astetik_*.png')
list.sort(file_list, key=lambda x: int(x.split('_')[1].split('.png')[0]))

with open('image_list.txt', 'w') as file:
for item in file_list:
file.write("%s\n" % item)

os.system('convert @image_list.txt {}.gif'.format(gif_name)) # magick on windows
140 changes: 140 additions & 0 deletions astetik/plots/bar1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# EXCEPTIONAL IMPORT #
import matplotlib
matplotlib.use('Agg')
# ENDS #

import matplotlib.pyplot as plt
from matplotlib.pyplot import rcParams
import seaborn as sns

from ..style.template import _header, _footer
from ..utils.utils import _limiter, _scaler
from ..utils.utils import factorplot_sizing
from ..style.titles import _titles


def bar1(data,
x,
y,
multi_color=False,
palette='default',
style='astetik',
dpi=72,
title='',
sub_title='',
x_label='',
y_label='',
legend=True,
x_scale='linear',
y_scale='linear',
x_limit='auto',
y_limit='auto',
save=False):

'''BAR PLOT
A 1-dimensional bar graph for the case where there is a single
value per label.
Inputs: 2
1. USE
======
ast.bar1d(data=patients,
x='icu_days',
y='insurance')
2. PARAMETERS
=============
2.1 INPUT PARAMETERS
--------------------
data :: pandas dataframe
x :: x-axis data (single value per label)
y :: y-axis data (labels)
--------------------
2.2. PLOT PARAMETERS
--------------------
multi_color :: If True, label values will be used for hue.
----------------------
2.3. COMMON PARAMETERS
----------------------
palette :: One of the astetik palettes:
'default'
'colorblind'
'blue_to_red'
'blue_to_green'
'red_to_green'
'green_to_red'
'violet_to_blue'
'brown_to_green'
'green_to_marine'
Or use any cmap, seaborn or matplotlib
color or palette code, or hex value.
style :: Use one of the three core styles:
'astetik' # white
'538' # grey
'solarized' # sepia
Or alternatively use any matplotlib or seaborn
style definition.
dpi :: the resolution of the plot (int value)
title :: the title of the plot (string value)
sub_title :: a secondary title to be shown below the title
x_label :: string value for x-axis label
y_label :: string value for y-axis label
x_scale :: 'linear' or 'log' or 'symlog'
y_scale :: 'linear' or 'log' or 'symlog'
x_limit :: int or list with two ints
y_limit :: int or list with two ints
outliers :: Remove outliers using either 'zscore' or 'iqr'
'''

size, aspect = factorplot_sizing(data[x])

if multi_color == True:
n_colors = len(data[x].unique())
else:
n_colors = 1

# HEADER STARTS >>>
palette = _header(palette,
style,
n_colors=n_colors,
dpi=dpi,
fig_height=None,
fig_width=None)
# <<< HEADER ENDS
p = sns.factorplot(data=data,
x=x,
y=y,
palette=palette,
aspect=aspect,
size=size,
kind='bar')

# SCALING AND LIMITS STARTS >>>
if x_scale != 'linear' or y_scale != 'linear':
_scaler(p, x_scale, y_scale)

# FOOTER STARTS >>>
_titles(title, sub_title=sub_title)
_footer(p, x_label, y_label, save=save)

if data[x].min() < 0:
sns.despine(left=True)
5 changes: 4 additions & 1 deletion astetik/plots/bars.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def bars(data,
A multi-dimension bar plot that takes up to 5 features at a time.
Inputs: 2 to 5
Features: At least one continuous (or stepped) variable and results
Features: At least one continuous (or stepped) variable and rest
can be categorical.
1. USE
Expand Down Expand Up @@ -116,6 +116,8 @@ def bars(data,
outliers :: Remove outliers using either 'zscore' or 'iqr'
'''

aspect = int(len(data[x].unique()) / 5)

if hue != None:
n_colors = len(data[hue].unique())
else:
Expand All @@ -137,6 +139,7 @@ def bars(data,
col=col,
col_wrap=col_wrap,
palette=palette,
aspect=aspect,
size=4,
kind='bar')

Expand Down
2 changes: 1 addition & 1 deletion astetik/plots/corr.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,4 @@ def corr(data,
_titles(title, sub_title=sub_title)
_footer(p, x_label, y_label, save=save)

p.set_xticklabels(data, rotation=45)
p.set_xticklabels(data)
13 changes: 9 additions & 4 deletions astetik/plots/count.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

def count(data,
x,
sort=None,
palette='default',
style='astetik',
dpi=72,
Expand Down Expand Up @@ -44,7 +45,7 @@ def count(data,
--------------------
2.2. PLOT PARAMETERS
--------------------
None
sort :: If True, will be sorted based on input values.
----------------------
2.3. COMMON PARAMETERS
Expand Down Expand Up @@ -95,6 +96,9 @@ def count(data,

aspect = int(len(data[x].unique()) / 5)

if sort != None:
sort = data[x].value_counts().index.values

# HEADER STARTS >>>
palette = _header(palette,
style,
Expand All @@ -104,17 +108,18 @@ def count(data,
fig_width=None)

p = sns.factorplot(data=data,
x=x,
y=x,
palette=palette,
size=4,
aspect=aspect,
kind='count',
legend=legend,
legend_out=False)
legend_out=False,
order=sort)

# FOOTER
_titles(title, sub_title)
_thousand_sep(p, p.ax)
_thousand_sep(p, p.ax, y_sep=False)
_footer(p, x_label, y_label, save=save)

p.set_xticklabels(None, rotation=90)
16 changes: 9 additions & 7 deletions astetik/plots/line.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.dates import HourLocator
from matplotlib import ticker

from ..style.formats import _thousand_sep
from ..style.style import params
Expand Down Expand Up @@ -164,7 +165,8 @@ def line(data,
func=interval_func,
freq=interval)

markers = ["o", "+", "x", "|", "-", ",", ".", "^", "v"]
markers = ["o", "+", "x", "|", "1", "8", "s", "p",
"o", "+", "x", "|", "1", "8", "s", "p"]
# <<< END OF PLOT SPECIFIC

# START OF HEADER >>>
Expand Down Expand Up @@ -205,7 +207,8 @@ def line(data,

# DATETIME FORMAT
if time_frame != None:
date_handler(data[x[0]], ax, time_frame)
data[y] = pd.to_datetime(data[y])
date_handler(data[y], ax, time_frame)

# LIMITS
if x_limit != None or y_limit != None:
Expand All @@ -217,7 +220,6 @@ def line(data,
_footer(p, x_label, y_label, save=save)

if legend != False:
plt.legend(x, loc=1, ncol=lines)
if y != None:
hours = HourLocator()
ax.xaxis.set_minor_locator(hours)
plt.legend(x, loc=1, ncol=1, bbox_to_anchor=(1.15, 1.0))

ax.xaxis.set_major_locator(ticker.MaxNLocator(nbins=8))
14 changes: 12 additions & 2 deletions astetik/plots/overlap.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

from ..style.titles import _titles
from ..style.template import _header
Expand All @@ -12,6 +13,7 @@ def overlap(data,
y,
label_col,
sort=None,
limit=None,
transform_func=False,
palette='default',
style='astetik',
Expand Down Expand Up @@ -67,6 +69,8 @@ def overlap(data,
sort :: either True or False for ascending sort based on the
x-axis data.
limit :: limit the number of items to be shown
transform_func :: If not False, the selected function such as
'mean' will be used to group by the label_col.
Available functions:
Expand Down Expand Up @@ -151,19 +155,25 @@ def overlap(data,
sns.barplot(data=data,
x=x,
y=label_col,
orient='h',
color=palette[0])

sns.barplot(data=data,
x=y,
y=label_col,
orient='h',
color=palette[1])

# # # # PLOT ENDS # # # #
if legend != False:
x_patch = mpatches.Patch(color=palette[0], label=x)
y_patch = mpatches.Patch(color=palette[1], label=y)
ax.legend(handles=[x_patch, y_patch], ncol=1, loc="upper right", frameon=True)

ax.legend(ncol=2, loc="lower right", frameon=True)
ax.set(ylabel=y_label, xlabel=x_label)
sns.despine(bottom=True)
ax.xaxis.set_major_locator(plt.MaxNLocator(5))

_thousand_sep(p, ax)
_titles(title, sub_title=sub_title)
if len(title) + len(sub_title) < 0:
_titles(title, sub_title=sub_title)
Loading

0 comments on commit cdc1afc

Please sign in to comment.