From c0f2e483e6b3a54f1437188452df61b022f5d31b Mon Sep 17 00:00:00 2001 From: Leo Date: Sun, 8 Nov 2015 22:57:03 +0000 Subject: [PATCH] fix release distribution --- MANIFEST | 4 + pyupset/Requirements.txt => Requirements.txt | 2 + dist/PyUpSet-0.1.1.post5.tar.gz | Bin 0 -> 52256 bytes pyupset/PyUpSet.egg-info/PKG-INFO | 14 - pyupset/PyUpSet.egg-info/SOURCES.txt | 6 - pyupset/PyUpSet.egg-info/dependency_links.txt | 1 - pyupset/PyUpSet.egg-info/requires.txt | 3 - pyupset/PyUpSet.egg-info/top_level.txt | 1 - pyupset/dist/PyUpSet-0.1.1.post1.tar.gz | Bin 1116 -> 0 bytes pyupset/setup.py => setup.py | 8 +- {pyupset => src/data}/test_data_dict.pckl | Bin src/pyupset/__init__.py | 2 + src/pyupset/visualisation.py | 650 ++++++++++++++++++ test_data_dict.pckl | Bin 0 -> 86980 bytes 14 files changed, 663 insertions(+), 28 deletions(-) rename pyupset/Requirements.txt => Requirements.txt (50%) create mode 100644 dist/PyUpSet-0.1.1.post5.tar.gz delete mode 100644 pyupset/PyUpSet.egg-info/PKG-INFO delete mode 100644 pyupset/PyUpSet.egg-info/SOURCES.txt delete mode 100644 pyupset/PyUpSet.egg-info/dependency_links.txt delete mode 100644 pyupset/PyUpSet.egg-info/requires.txt delete mode 100644 pyupset/PyUpSet.egg-info/top_level.txt delete mode 100644 pyupset/dist/PyUpSet-0.1.1.post1.tar.gz rename pyupset/setup.py => setup.py (77%) rename {pyupset => src/data}/test_data_dict.pckl (100%) create mode 100644 src/pyupset/__init__.py create mode 100644 src/pyupset/visualisation.py create mode 100644 test_data_dict.pckl diff --git a/MANIFEST b/MANIFEST index d2385e4..7f44e89 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,2 +1,6 @@ # file GENERATED by distutils, do NOT edit +README.txt setup.py +src/data/test_data_dict.pckl +src/pyupset/__init__.py +src/pyupset/visualisation.py diff --git a/pyupset/Requirements.txt b/Requirements.txt similarity index 50% rename from pyupset/Requirements.txt rename to Requirements.txt index 3f4972e..618882a 100644 --- a/pyupset/Requirements.txt +++ b/Requirements.txt @@ -1,3 +1,5 @@ +--index-url https://pypi.python.org/pypi/pyupset + matplotlib == 1.4.3 pandas == 0.16.2 numpy == 1.9.2 diff --git a/dist/PyUpSet-0.1.1.post5.tar.gz b/dist/PyUpSet-0.1.1.post5.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..3968e46b51775860304daaac766c65d91d7ba5a4 GIT binary patch literal 52256 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 z

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 V+F$!?fBlGG{|BtPvJn6X0sz<7Hn;!) literal 0 HcmV?d00001 diff --git a/pyupset/PyUpSet.egg-info/PKG-INFO b/pyupset/PyUpSet.egg-info/PKG-INFO deleted file mode 100644 index 7e766ad..0000000 --- a/pyupset/PyUpSet.egg-info/PKG-INFO +++ /dev/null @@ -1,14 +0,0 @@ -Metadata-Version: 1.1 -Name: PyUpSet -Version: 0.1.1.post1 -Summary: Python implementation of the UpSet visualisation suite by Lex et al. -Home-page: https://github.com/ImSoErgodic/py-upset -Author: Leonardo Baldassini -Author-email: leo@opensignal.com -License: MIT -Description: UNKNOWN -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Science/Research -Classifier: Topic :: Scientific/Engineering :: Visualization -Classifier: Programming Language :: Python :: 3 diff --git a/pyupset/PyUpSet.egg-info/SOURCES.txt b/pyupset/PyUpSet.egg-info/SOURCES.txt deleted file mode 100644 index 92fa403..0000000 --- a/pyupset/PyUpSet.egg-info/SOURCES.txt +++ /dev/null @@ -1,6 +0,0 @@ -setup.py -PyUpSet.egg-info/PKG-INFO -PyUpSet.egg-info/SOURCES.txt -PyUpSet.egg-info/dependency_links.txt -PyUpSet.egg-info/requires.txt -PyUpSet.egg-info/top_level.txt \ No newline at end of file diff --git a/pyupset/PyUpSet.egg-info/dependency_links.txt b/pyupset/PyUpSet.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/pyupset/PyUpSet.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/pyupset/PyUpSet.egg-info/requires.txt b/pyupset/PyUpSet.egg-info/requires.txt deleted file mode 100644 index 7de02f0..0000000 --- a/pyupset/PyUpSet.egg-info/requires.txt +++ /dev/null @@ -1,3 +0,0 @@ -pandas -matplotlib -numpy diff --git a/pyupset/PyUpSet.egg-info/top_level.txt b/pyupset/PyUpSet.egg-info/top_level.txt deleted file mode 100644 index 8b13789..0000000 --- a/pyupset/PyUpSet.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/pyupset/dist/PyUpSet-0.1.1.post1.tar.gz b/pyupset/dist/PyUpSet-0.1.1.post1.tar.gz deleted file mode 100644 index f5a40a2e279a474d41162dc91baabff9a1cbd002..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1116 zcmV-i1f%;OiwFqdJ=0YJ|72-%bT3eORd7>fbS*G0F)lGKaBp*TF)nmrascg_TW{Mo z6vzF{PeEW0N`UwxUjYLK*0tFdG;xeN=^lbWpe0%+LXjLv8Fhz!_mPrgH%^+^jpy!i zetwWh9+DEtb4dL?T3o9!wbe!~bU!7H4eOOX({S`Uo$}i47S~3zU0zEnVYAb1cU#?F zyHRO`ZD&})oyq~ojU^i6$~l$K+Bvi7^o5u7FLHnVmoR!_{zvbBsh$mgzTD^hciZi+ z&41_;8}r|B>!pGlF#mr$7u1r3SW^8+wP8~9v0DddNHW^T%e8@4MPDouG|sb(=!Lhk zGbu336sH*#mRM(tn&P+}?Gi8yZ(62J1RYg+Q>&#kZ z`t^Fs>@1(uVwu&?vavkXsZ3a0SBq+{jC-m#x$9T=T`N)$ok;u>;R!K@3AQY&(u^?P z$DGO^rJ};HRJhJui|CxiF70}|IJ-jcsEIXGws^+~I+Q!bT%Up#iNoEzNl;|{Lkk(Nmw`?l(?V8ZExdS}8?ka{q`4bmUt>9E z?yiL@!2g&h)#U`qmW(?A8BYIUl?0KVhc_ z`#7M#{(f^&ZZ~Xt;ZGrxC5N=$Mk9?57MV6#dLM+7t+$a*0obkk^ ziiDYqNYgpE_|k>kJZ|7uY=jQ@w7u)FsEX6XID(}ey1AVd)Ld&^w&L9nGdzN*Aap?eTq zoL#LlZkM2J+2RA_}bOk3k zSZiHARmffIn#-l^H$pP_Be2xi;y!Yt>mP{dMbN+5$gipRjt94Y9>abD0000000000 i000000000000000000000000ShQ9!JksQMSPyhg23_S+` diff --git a/pyupset/setup.py b/setup.py similarity index 77% rename from pyupset/setup.py rename to setup.py index 1a77ad6..8b8cbde 100644 --- a/pyupset/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ __author__ = 'leo@opensignal.com' -from setuptools import setup, find_packages +from distutils.core import setup # To use a consistent encoding from codecs import open from os import path @@ -8,7 +8,7 @@ setup(name='PyUpSet', - version='0.1.1.post1', + version='0.1.1.post5', description='Python implementation of the UpSet visualisation suite by Lex et al.', author = 'Leonardo Baldassini', author_email= 'leo@opensignal.com', @@ -20,4 +20,6 @@ 'Topic :: Scientific/Engineering :: Visualization', 'Programming Language :: Python :: 3'], install_requires=['pandas', 'matplotlib', 'numpy'], - package_data={'test_data_dictionary':['test_data_dict.pckl']}) \ No newline at end of file + packages=['pyupset'], + package_dir={'pyupset':'src/pyupset'}, + package_data={'pyupset':['src/data/test_data_dict.pckl']}) diff --git a/pyupset/test_data_dict.pckl b/src/data/test_data_dict.pckl similarity index 100% rename from pyupset/test_data_dict.pckl rename to src/data/test_data_dict.pckl diff --git a/src/pyupset/__init__.py b/src/pyupset/__init__.py new file mode 100644 index 0000000..23909ac --- /dev/null +++ b/src/pyupset/__init__.py @@ -0,0 +1,2 @@ +__author__ = 'leo@opensignal.com' +from .visualisation import plot \ No newline at end of file diff --git a/src/pyupset/visualisation.py b/src/pyupset/visualisation.py new file mode 100644 index 0000000..7f41440 --- /dev/null +++ b/src/pyupset/visualisation.py @@ -0,0 +1,650 @@ +__author__ = 'leo@opensignal.com' + +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +from matplotlib import gridspec +from itertools import chain, combinations +from functools import partial +from matplotlib.patches import Rectangle, Circle + + + +def plot(data_dict, *, unique_keys=None, sort_by='size', inters_size_bounds=(0, np.inf), + inters_degree_bounds=(1, np.inf), additional_plots=None, query=None): + """ + Plots a main set of graph showing intersection size, intersection matrix and the size of base sets. If given, + additional plots are placed below the main graph. + + :param data_dict: dictionary like {data_frame_name: data_frame} + + :param unique_keys: list. Specifies the names of the columns that, together, can uniquely identify a row. If left + empty, pyUpSet will try to use all common columns in the data frames and may possibly raise an exception (no + common columns) or produce unexpected results (columns in different data frames with same name but different + meanings/data). + + :param sort_by: 'size' or 'degree'. The order in which to sort the intersection bar chart and matrix in the main + graph + + :param inters_size_bounds: tuple. Specifies the size limits of the intersections that will be displayed. + Intersections (and relative data) whose size is outside the interval will not be plotted. Defaults to (0, np.inf). + + :param inters_degree_bounds: tuple. Specified the degree limits of the intersections that will be displayed. + Intersections (and relative data) whose degree is outside the interval will not be plotted. Defaults to (0, np.inf). + + :param additional_plots: list of dictionaries. See below for details. + + :param query: list of tuples. See below for details. + + :return: dictionary of matplotlib objects, namely the figure and the axes. + + :raise ValueError: if no unique_keys are specified and the data frames have no common column names. + + The syntax to specify additional plots follows the signature of the corresponding matplotlib method in an Axes + class. For each additional plot one specifies a dictionary with the kind of plot, the columns name to retrieve + relevant data and the kwargs to pass to the plot function, as in `{'kind':'scatter', 'data':{'x':'col_1', + 'y':'col_2'}, 'kwargs':{'s':50}}`. + + Currently supported additional plots: scatter. + + It is also possible to highlight intersections. This is done through the `query` argument, where the + intersections to highligh must be specified with the names used as keys in the data_dict. + + """ + query = [] if query is None else query + ap = [] if additional_plots is None else additional_plots + all_columns = unique_keys if unique_keys is not None else __get_all_common_columns(data_dict) + all_columns = list(all_columns) + + plot_data = DataExtractor(data_dict, all_columns) + ordered_inters_sizes, ordered_in_sets, ordered_out_sets = plot_data.get_filtered_intersections(sort_by, + inters_size_bounds, + inters_degree_bounds) + ordered_dfs, ordered_df_names = plot_data.ordered_dfs, plot_data.ordered_df_names + + upset = UpSetPlot(len(ordered_dfs), len(ordered_in_sets), additional_plots, query) + fig_dict = upset.main_plot(ordered_dfs, ordered_df_names, ordered_in_sets, ordered_out_sets, + ordered_inters_sizes) + fig_dict['additional'] = [] + + + # ap = [{kind:'', data:{x:'', y:''}, s:'', ..., kwargs:''}] + for i, graph_settings in enumerate(ap): + plot_kind = graph_settings.pop('kind') + data_vars = graph_settings.pop('data_quantities') + graph_properties = graph_settings.get('graph_properties', {}) + data_values = plot_data.extract_data_for(data_vars, query) + ax = upset.additional_plot(i, plot_kind, data_values, graph_properties, labels=data_vars) + fig_dict['additional'].append(ax) + + return fig_dict + + +def __get_all_common_columns(data_dict): + """ + Computes an array of (unique) common columns to the data frames in data_dict + :param data_dict: Dictionary of data frames + :return: array. + """ + common_columns = [] + for i, k in enumerate(data_dict.keys()): + if i == 0: + common_columns = data_dict[k].columns + else: + common_columns = common_columns.intersection(data_dict[k].columns) + if len(common_columns.values) == 0: + raise ValueError('Data frames should have homogeneous columns with the same name to use for computing ' + 'intersections') + return common_columns.unique() + + +class UpSetPlot(): + def __init__(self, rows, cols, additional_plots, query): + """ + Generates figures and axes. + + :param rows: The number of rows of the intersection matrix + + :param cols: The number of columns of the intersection matrix + + :param additional_plots: list of dictionaries as specified in plot() + + :param query: list of tuples as specified in plot() + """ + + # set standard colors + self.greys = plt.cm.Greys([.22, .8]) + + # map queries to graphic properties + self.query = query + qu_col = plt.cm.rainbow(np.linspace(.01, .99, len(self.query))) + self.query2color = dict(zip([frozenset(q) for q in self.query], qu_col)) + self.query2zorder = dict(zip([frozenset(q) for q in self.query], np.arange(len(self.query)) + 1)) + + # set figure properties + self.rows = rows + self.cols = cols + self.x_values, self.y_values = self._create_coordinates(rows, cols) + self.fig, self.ax_intbars, self.ax_intmatrix, \ + self.ax_setsize, self.ax_tablenames, self.additional_plots_axes = self._prepare_figure(additional_plots) + + self.standard_graph_settings = { + 'scatter': { + 'alpha': .3, + 'edgecolor': None + }, + 'hist': { + 'histtype': 'stepfilled', + 'alpha': .3, + 'lw': 0 + } + } + + # single dictionary may be fragile - I leave it here as a future option + # self.query2kwargs = dict(zip([frozenset(q) for q in self.query], + # [dict(zip(['color', 'zorder'], + # [col, 1])) for col in qu_col])) + + def _create_coordinates(self, rows, cols): + """ + Creates the x, y coordinates shared by the main plots. + + :param rows: number of rows of intersection matrix + :param cols: number of columns of intersection matrix + :return: arrays with x and y coordinates + """ + x_values = (np.arange(cols) + 1) + y_values = (np.arange(rows) + 1) + return x_values, y_values + + def _prepare_figure(self, additional_plots): + """ + Prepares the figure, axes (and their grid) taking into account the additional plots. + + :param additional_plots: list of dictionaries as specified in plot() + :return: references to the newly created figure and axes + """ + fig = plt.figure(figsize=(17, 10.5)) + if additional_plots: + main_gs = gridspec.GridSpec(3, 1, hspace=.4) + topgs = main_gs[:2, 0] + botgs = main_gs[2, 0] + else: + topgs = gridspec.GridSpec(1, 1)[0, 0] + fig_cols = self.cols + 5 + fig_rows = self.rows + self.rows * 4 + + gs_top = gridspec.GridSpecFromSubplotSpec(fig_rows, fig_cols, subplot_spec=topgs, wspace=.1, hspace=.2) + setsize_w, setsize_h = 3, self.rows + tablesize_w, tablesize_h = setsize_w + 2, self.rows + intmatrix_w, intmatrix_h = tablesize_w + self.cols, self.rows + intbars_w, intbars_h = tablesize_w + self.cols, self.rows * 4 + ax_setsize = plt.subplot(gs_top[-1:-setsize_h, 0:setsize_w]) + ax_tablenames = plt.subplot(gs_top[-1:-tablesize_h, setsize_w:tablesize_w]) + ax_intmatrix = plt.subplot(gs_top[-1:-intmatrix_h, tablesize_w:intmatrix_w]) + ax_intbars = plt.subplot(gs_top[:self.rows * 4 - 1, tablesize_w:intbars_w]) + + add_ax = [] + if additional_plots: + num_plots = len(additional_plots) + num_bot_rows, num_bot_cols = int(np.ceil(num_plots / 2)), 2 + gs_bottom = gridspec.GridSpecFromSubplotSpec(num_bot_rows, num_bot_cols, + subplot_spec=botgs, wspace=.15, hspace=.2) + from itertools import product + + for r, c in product(range(num_bot_rows), range(num_bot_cols)): + new_plotL = plt.subplot(gs_bottom[r, c]) + add_ax.append(new_plotL) + + return fig, ax_intbars, ax_intmatrix, ax_setsize, ax_tablenames, tuple(add_ax) + + def _color_for_query(self, query): + """ + Helper function that returns the standard dark grey for non-queried intersections, and the color assigned to + a query when the class was instantiated otherwise + :param query: frozenset. + :return: color as length 4 array. + """ + query_color = self.query2color.setdefault(query, self.greys[1]) + return query_color + + def _zorder_for_query(self, query): + """ + Helper function that returns 0 for non-queried intersections, and the zorder assigned to + a query when the class was instantiated otherwise + :param query: frozenset. + :return: zorder as int. + """ + query_zorder = self.query2zorder.setdefault(query, 0) + return query_zorder + + def main_plot(self, ordered_dfs, ordered_df_names, ordered_in_sets, ordered_out_sets, ordered_inters_sizes): + """ + Creates the main graph comprising bar plot of base set sizes, bar plot of intersection sizes and intersection + matrix. + + :param ordered_dfs: array of input data frames, sorted w.r.t. the sorting parameters provided by the user (if + any) + + :param ordered_df_names: array of names of input data frames, sorted (as above) + + :param ordered_in_sets: list of tuples. Each tuple represents an intersection. The list must be sorted as the + other parameters. + + :param ordered_out_sets: list of tuples. Each tuple represents the sets excluded from the corresponding + intersection described by ordered_in_sets. + + :param ordered_inters_sizes: array of ints. Contains the intersection sizes, sorted as the other arguments. + + :return: dictionary containing figure and axes references. + """ + ylim = self._base_sets_plot(ordered_dfs, ordered_df_names) + self._table_names_plot(ordered_df_names, ylim) + xlim = self._inters_sizes_plot(ordered_in_sets, ordered_inters_sizes) + set_row_map = dict(zip(ordered_df_names, self.y_values)) + self._inters_matrix(ordered_in_sets, ordered_out_sets, xlim, ylim, set_row_map) + return {'figure': self.fig, + 'intersection_bars': self.ax_intbars, + 'intersection_matrix': self.ax_intmatrix, + 'base_set_size': self.ax_setsize, + 'names':self.ax_tablenames} + + def _table_names_plot(self, sorted_set_names, ylim): + ax = self.ax_tablenames + ax.set_ylim(ylim) + xlim = ax.get_xlim() + tr = ax.transData.transform + for i, name in enumerate(sorted_set_names): + ax.text(x = 1,#(xlim[1]-xlim[0]/2), + y = self.y_values[i], + s = name, + fontsize = 14, + clip_on=True, + va='center', + ha='right', + transform=ax.transData, + family='monospace') + + # if len(self.x_values) > 1: + # row_width = self.x_values[1] - self.x_values[0] + # else: + # row_width = self.x_values[0] + # + # background = plt.cm.Greys([.09])[0] + # + # for r, y in enumerate(self.y_values): + # if r % 2 == 0: + # ax.add_patch(Rectangle((xlim[0], y - row_width / 2), height=row_width, + # width=xlim[1], + # color=background, zorder=0)) + ax.axis('off') + + + def _base_sets_plot(self, sorted_sets, sorted_set_names): + """ + Plots horizontal bar plot for base set sizes. + + :param sorted_sets: list of data frames, sorted according to user's directives. + :param sorted_set_names: list of names for the data frames. + :return: Axes. + """ + ax = self.ax_setsize + ax.invert_xaxis() + height = .6 + bar_bottoms = self.y_values - height / 2 + + ax.barh(bar_bottoms, [len(x) for x in sorted_sets], height=height, color=self.greys[1]) + + ax.ticklabel_format(style='sci', axis='x', scilimits=(0, 4)) + + self._strip_axes(ax, keep_spines=['bottom'], keep_ticklabels=['bottom']) + + ax.set_ylim((height / 2, ax.get_ylim()[1] + height / 2)) + xlim = ax.get_xlim() + gap = max(xlim) / 500.0 * 20 + ax.set_xlim(xlim[0] + gap, xlim[1] - gap) + xlim = ax.get_xlim() + ax.spines['bottom'].set_bounds(xlim[0], xlim[1]) + + # bracket_height = ax.transData.inverted().transform([(0, 0), (0, ax.get_ylim()[1])]) + # bracket_height = np.abs(bracket_height[1, 1] - bracket_height[0, 1]) + # for i, (x, y) in enumerate(zip([len(x) for x in sorted_sets], self.y_values)): + # ax.annotate(sorted_set_names[i], rotation=90, ha='right', va='bottom', fontsize=15, + # xy=(x, y), xycoords='data', + # xytext=(-30, 0), textcoords='offset points', + # arrowprops=dict(arrowstyle="-[, widthB=%s"%(bracket_height,), + # shrinkA=1, + # shrinkB=3, + # connectionstyle='arc,angleA=-180, angleB=180, armB=30', + # ), + # ) + + ax.set_xlabel("Set size", fontweight='bold', fontsize=13) + + return ax.get_ylim() + + def _strip_axes(self, ax, keep_spines=None, keep_ticklabels=None): + """ + Removes spines and tick labels from ax, except those specified by the user. + + :param ax: Axes on which to operate. + :param keep_spines: Names of spines to keep. + :param keep_ticklabels: Names of tick labels to keep. + + Possible names are 'left'|'right'|'top'|'bottom'. + """ + tick_params_dict = {'which': 'both', + 'bottom': 'off', + 'top': 'off', + 'left': 'off', + 'right': 'off', + 'labelbottom': 'off', + 'labeltop': 'off', + 'labelleft': 'off', + 'labelright': 'off'} + if keep_ticklabels is None: + keep_ticklabels = [] + if keep_spines is None: + keep_spines = [] + lab_keys = [(k, "".join(["label", k])) for k in keep_ticklabels] + for k in lab_keys: + tick_params_dict[k[0]] = 'on' + tick_params_dict[k[1]] = 'on' + ax.tick_params(**tick_params_dict) + for sname, spine in ax.spines.items(): + if sname not in keep_spines: + spine.set_visible(False) + + def _inters_sizes_plot(self, ordered_in_sets, inters_sizes): + """ + Plots bar plot for intersection sizes. + :param ordered_in_sets: array of tuples. Each tuple represents an intersection. The array is sorted according + to the user's directives + + :param inters_sizes: array of ints. Sorted, likewise. + + :return: Axes + """ + ax = self.ax_intbars + width = .5 + self._strip_axes(ax, keep_spines=['left'], keep_ticklabels=['left']) + + bar_bottom_left = self.x_values - width / 2 + + bar_colors = [self._color_for_query(frozenset(inter)) for inter in ordered_in_sets] + + ax.bar(bar_bottom_left, inters_sizes, width=width, color=bar_colors, linewidth=0) + + ylim = ax.get_ylim() + label_vertical_gap = (ylim[1] - ylim[0]) / 60 + + for x, y in zip(self.x_values, inters_sizes): + ax.text(x, y + label_vertical_gap, "%.2g" % y, + rotation=90, ha='center', va='bottom') + + ax.ticklabel_format(style='sci', axis='y', scilimits=(0, 4)) + + gap = max(ylim) / 500.0 * 20 + ax.set_ylim(ylim[0] - gap, ylim[1] + gap) + ylim = ax.get_ylim() + ax.spines['left'].set_bounds(ylim[0], ylim[1]) + + ax.yaxis.grid(True, lw=.25, color='grey', ls=':') + ax.set_axisbelow(True) + ax.set_ylabel("Intersection size", labelpad=6, fontweight='bold', fontsize=13) + + return ax.get_xlim() + + def _inters_matrix(self, ordered_in_sets, ordered_out_sets, xlims, ylims, set_row_map): + """ + Plots intersection matrix. + + :param ordered_in_sets: Array of tuples representing sets included in an intersection. Sorted according to + the user's directives. + + :param ordered_out_sets: Array of tuples representing sets excluded from an intersection. Sorted likewise. + + :param xlims: tuple. x limits for the intersection matrix plot. + + :param ylims: tuple. y limits for the intersection matrix plot. + + :param set_row_map: dict. Maps data frames (base sets) names to a row of the intersection matrix + + :return: Axes + """ + ax = self.ax_intmatrix + ax.set_xlim(xlims) + ax.set_ylim(ylims) + + if len(self.x_values) > 1: + row_width = self.x_values[1] - self.x_values[0] + else: + row_width = self.x_values[0] + + self._strip_axes(ax) + + background = plt.cm.Greys([.09])[0] + + for r, y in enumerate(self.y_values): + if r % 2 == 0: + ax.add_patch(Rectangle((xlims[0], y - row_width / 2), height=row_width, + width=xlims[1], + color=background, zorder=0)) + + for col_num, (in_sets, out_sets) in enumerate(zip(ordered_in_sets, ordered_out_sets)): + in_y = [set_row_map[s] for s in in_sets] + out_y = [set_row_map[s] for s in out_sets] + # in_circles = [Circle((self.x_values[col_num], y), radius=dot_size, color=self.greys[1]) for y in in_y] + # out_circles = [Circle((self.x_values[col_num], y), radius=dot_size, color=self.greys[0]) for y in out_y] + # for c in chain.from_iterable([in_circles, out_circles]): + # ax.add_patch(c) + ax.scatter(np.repeat(self.x_values[col_num], len(in_y)), in_y, color=self._color_for_query(frozenset( + in_sets)), s=300) + ax.scatter(np.repeat(self.x_values[col_num], len(out_y)), out_y, color=self.greys[0], s=300) + ax.vlines(self.x_values[col_num], min(in_y), max(in_y), lw=3.5, color=self._color_for_query(frozenset( + in_sets))) + + def additional_plot(self, ax_index, kind, data_values, graph_args, *, labels=None): + """ + Scatter plot (for additional plots). + + :param ax_index: int. Index for the relevant axes (additional plots' axes are stored in a list) + + :param data_values: list of dictionary. Each dictionary is like {'x':data_for_x, 'y':data_for_y, + 'in_sets':tuple}, where the tuple represents the intersection the data for x and y belongs to. + + :param plot_kwargs: kwargs accepted by matplotlib scatter + + :param labels: dictionary. {'x':'x_label', 'y':'y_label'} + + :return: Axes + """ + ax = self.additional_plots_axes[ax_index] + + plot_method = getattr(ax, kind) + + for k, v in self.standard_graph_settings.get(kind, {}).items(): + graph_args.setdefault(k, v) + + plot_method = partial(plot_method, **graph_args) + + # data_values = [{query:{relevant data}}] + ylim, xlim = [np.inf, -np.inf], [np.inf, -np.inf] + for query, data_item in data_values.items(): + plot_method(color=self._color_for_query(frozenset(query)), + zorder=self._zorder_for_query(frozenset(query)), + **data_item + ) + new_xlim, new_ylim = ax.get_xlim(), ax.get_ylim() + for old, new in zip([xlim, ylim], [new_xlim, new_ylim]): + old[0] = new[0] if old[0] > new[0] else old[0] + old[1] = new[1] if old[1] < new[1] else old[1] + + ax.ticklabel_format(style='sci', axis='y', scilimits=(0, 4)) + + self._strip_axes(ax, keep_spines=['bottom', 'left'], keep_ticklabels=['bottom', 'left']) + # ylim, xlim = ax.get_ylim(), ax.get_xlim() + gap_y, gap_x = max(ylim) / 500.0 * 20, max(xlim) / 500.0 * 20 + ax.set_ylim(ylim[0] - gap_y, ylim[1] + gap_y) + ax.set_xlim(xlim[0] - gap_x, xlim[1] + gap_x) + ylim, xlim = ax.get_ylim(), ax.get_xlim() + ax.spines['left'].set_bounds(ylim[0], ylim[1]) + ax.spines['bottom'].set_bounds(xlim[0], xlim[1]) + + for l, text in labels.items(): + getattr(ax, 'set_%slabel' % l)(text, labelpad=3, + fontweight='bold', fontsize=13) if l in ['x', 'y'] else None + return ax + + +class DataExtractor: + def __init__(self, data_dict, unique_keys): + """ + Packages the data in a way that can be consumed by the plot methods in UpSetPlot. + + :param data_dict: dict. {'name': pandas DataFrame} + + :param unique_keys: list of names of columns that uniquely identify a row in the data frames. + """ + self.unique_keys = unique_keys if len(unique_keys) > 1 else unique_keys[0] + self.ordered_dfs, self.ordered_df_names, self.df_dict = self.extract_base_sets_data(data_dict, + unique_keys) + self.in_sets_list, self.inters_degrees, \ + self.out_sets_list, self.inters_df_dict = self.extract_intersection_data() + + + def extract_base_sets_data(self, data_dict, unique_keys): + """ + Extracts data for the bar graph of the base sets sizes. + + :param data_dict: dict. {'name': data frame} + + :param unique_keys: list of column names to uniquely identify rows. + + :return: list of data frames sorted by shape[0], list of names sorted accordingly, dictionary zipping the two. + """ + dfs = [] + df_names = [] + # extract interesting columns from dfs + for name, df in data_dict.items(): + df_names.append(name) + dfs.append(df[unique_keys]) + df_names = np.array(df_names) + # order dfs + base_sets_order = np.argsort([x.shape[0] for x in dfs])[::-1] + ordered_base_set_names = df_names[base_sets_order] + ordered_base_sets = [data_dict[name] for name in ordered_base_set_names] + set_dict = dict(zip(ordered_base_set_names, ordered_base_sets)) + + return ordered_base_sets, ordered_base_set_names, set_dict + + def extract_intersection_data(self): + """ + Extract data to use in intersection bar plot and matrix. + + :return: list of tuples (sets included in intersections), list of integers (corresponding degrees of + intersections), list of tuples (sets excluded from intersections), dict {tuple:data frame}, where each data + frame contains only the rows corresponding to the intersection described by the tuple-key. + """ + in_sets_list = [] + out_sets_list = [] + inters_dict = {} + inters_degrees = [] + for col_num, in_sets in enumerate(chain.from_iterable( + combinations(self.ordered_df_names, i) for i in np.arange(1, len(self.ordered_dfs) + 1))): + + in_sets = frozenset(in_sets) + + inters_degrees.append(len(in_sets)) + in_sets_list.append(in_sets) + out_sets = set(self.ordered_df_names).difference(set(in_sets)) + in_sets_l = list(in_sets) + out_sets_list.append(set(out_sets)) + + seed = in_sets_l.pop() + exclusive_intersection = pd.Index(self.df_dict[seed][self.unique_keys]) + for s in in_sets_l: + exclusive_intersection = exclusive_intersection.intersection(pd.Index(self.df_dict[s][ + self.unique_keys])) + for s in out_sets: + exclusive_intersection = exclusive_intersection.difference(pd.Index(self.df_dict[s][ + self.unique_keys])) + final_df = self.df_dict[seed].set_index(pd.Index(self.df_dict[seed][self.unique_keys])).ix[ + exclusive_intersection].reset_index(drop=True) + inters_dict[in_sets] = final_df + + return in_sets_list, inters_degrees, out_sets_list, inters_dict + + def get_filtered_intersections(self, sort_by, inters_size_bounds, inters_degree_bounds): + """ + Filter the intersection data according to the user's directives and return it. + + :param sort_by: 'degree'|'size'. Whether to sort intersections by degree or size. + :param inters_size_bounds: tuple. Specifies the size interval of the intersections that will be plotted. + :param inters_degree_bounds: tuple. Specifies the degree interval of the intersections that will be plotted. + :return: Array of int (sizes), array of tuples (sets included in intersection), array of tuples (sets + excluded from intersection), all filtered and sorted. + """ + inters_sizes = np.array([self.inters_df_dict[x].shape[0] for x in self.in_sets_list]) + inters_degrees = np.array(self.inters_degrees) + + size_clip = (inters_sizes <= inters_size_bounds[1]) & (inters_sizes >= inters_size_bounds[0]) & ( + inters_degrees >= inters_degree_bounds[0]) & (inters_degrees <= inters_degree_bounds[1]) + + in_sets_list = np.array(self.in_sets_list)[size_clip] + out_sets_list = np.array(self.out_sets_list)[size_clip] + inters_sizes = inters_sizes[size_clip] + inters_degrees = inters_degrees[size_clip] + + # sort as requested + if sort_by == 'size': + order = np.argsort(inters_sizes)[::-1] + elif sort_by == 'degree': + order = np.argsort(inters_degrees) + + # store ordered data + self.filtered_inters_sizes = inters_sizes[order] + self.filtered_in_sets = in_sets_list[order] + self.filtered_out_sets = out_sets_list[order] + + return self.filtered_inters_sizes, self.filtered_in_sets, self.filtered_out_sets + + def extract_data_for(self, var_dict, queries): + """ + Extract data from named columns (values) and place in named variables (keys). + + :return: list of dict. [{query:{x:, y:, ...}}] + """ + data_values = {} + for q in queries: + data_values[q] = dict(zip(var_dict.keys(), + [self.inters_df_dict[frozenset(q)][v].values for k, v in var_dict.items()])) + data_values['others'] = dict(zip(var_dict.keys(), + [chain(*[self.inters_df_dict[frozenset(q)][v].values for q in self.filtered_in_sets if q not in queries]) + for k, v in var_dict.items()])) + for k, vals in data_values['others'].items(): + data_values['others'][k] = [x for x in vals] + + return data_values + + +if __name__ == '__main__': + from pickle import load + + f = open('./test_data_dict.pckl', 'rb') + data_dict = load(f) + f.close() + plot(data_dict, unique_keys=['title'], + query=[('action',), ('romance', 'action'), ('romance',)], + additional_plots=[{'kind': 'scatter', + 'data_quantities': {'x': 'rating_avg', 'y': 'views'}, + 'graph_properties':{'alpha':.3, 'edgecolor':'w', 'lw':.3}}, + {'kind': 'hist', + 'data_quantities': {'x': 'views'}, + 'graph_properties':{'bins':10, 'normed':1, 'alpha':.6}}] + ) + + +# TODO: if possible, remove horrible hack that uses Index instead of pd.merge +# TODO: adjust figure size depending on number of graphs +# TODO: add comments? diff --git a/test_data_dict.pckl b/test_data_dict.pckl new file mode 100644 index 0000000000000000000000000000000000000000..56cdf99f720105c8d10a741eb386d002d8a708ef GIT binary patch literal 86980 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঑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 literal 0 HcmV?d00001