def slope(data, kind='interval', marker='%0.f', color=None, title='', font_family='GillSans', font_size=12, width=12, height=8, ax=None, savename=None, dpi=150, wspace=None, ): """==== Slope ==== Definition: slope(data,kind=['interval','ordinal'],height,width,font_size,savename,color,title) ---- Plot Slope plot Tufte Style :class:`matplotlib.figure.Figure object`. Parameters ---------- data : pandas dataFrame index indicate the categories columns indicate time / period marker style : str, format Format to present the data default '%0.f' label_position : str ['ordinal', 'interval'] how to position labels. Interval will place them according to their values Ordinal will place them according to their rank font_family : font family name installed on your system font_size : set the font size in case your data have more lines than you can have text lines of text in your figure height, data will be binned to fit (default 12) height : Figure height in inches (default 12) with : Figure width in inches (default 8) savename : file path to save your graph color : a dictionary {label:color} title : a title at the bottom of the graph Examples -------- >>> data = pd.read_csv(os.path.join('Data','EU_GDP_2007_2013.csv'),index_col=0,na_values='-') >>> f = slope(data/1000,kind='interval',height= 12,width=20,font_size=12,savename='EU_interval.png',title = u'title') """ font = FontProperties(font_family) font.set_size(font_size) bx = None df = data.copy() cols = df.columns df['__label__'] = df.index df['__order__'] = range(len(df.index)) if kind == 'stack': f, axarr = plt.subplots(len(df), len(cols) - 1, facecolor="w", squeeze=False, sharex=True) #,sharey=True) else: #f, axarr = plt.subplots(2,len(cols)-1,facecolor="w",squeeze=True,figsize=(width,height),dpi=30)#,sharex=True)#,sharey=True) f = plt.figure(figsize=(width, height), dpi=30, facecolor="w") gs = gridspec.GridSpec( nrows=20, ncols=len(cols) - 1 ) # the 20 rows are just there to provide enought space for the title axarr = [] axarr_X = [] for i in range(len(cols) - 1): axarr.append(plt.subplot(gs[:19, i])) axarr_X.append(plt.subplot(gs[19, i])) axarr = np.array(axarr) axarr_X = np.array(axarr_X) renderer = f.canvas.get_renderer() data_range = [data.min().min(), data.max().max()] fh = f.get_figheight() fw = f.get_figwidth() fdpi = f.get_dpi() nt = fh // (font.get_size() / 72) / 2 res = np.diff(data_range)[0] / nt * 2 if not hasattr(axarr, 'transpose'): axarr = [axarr] for i in range((len(cols) - 1)): ax = axarr[i] axarr_X[i].yaxis.set_tick_params(width=0) axarr_X[i].xaxis.set_tick_params(width=0) """ from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker # orange label obox1 = TextArea("orange - ", textprops=dict(color="k", size=15)) obox2 = TextArea("5 ", textprops=dict(color="b", size=15)) obox3 = TextArea(": ", textprops=dict(color="k", size=15)) obox4 = TextArea("10 ", textprops=dict(color="r", size=15)) orangebox = HPacker(children=[obox1, obox2, obox3, obox4], align="center", pad=0, sep=5) """ if kind == 'interval': labelsL = df.groupby(pd.cut(df[cols[i]], nt))['__label__'].agg( ', '.join).dropna() labelsR = df.groupby(pd.cut(df[cols[i + 1]], nt))['__label__'].agg( ', '.join).dropna() yPos_L = df.groupby(pd.cut(df[cols[i]], nt))[cols[i]].mean().dropna() yPos_R = df.groupby(pd.cut(df[cols[i + 1]], nt))[cols[i + 1]].mean().dropna() yMark_L = df.groupby(pd.cut(df[cols[i]], nt))[cols[i]].mean().dropna() yMark_R = df.groupby(pd.cut(df[cols[i + 1]], nt))[cols[i + 1]].mean().dropna() yPos_ = df[[cols[i], cols[i + 1]]] if kind == 'ordinal': yPos_L = df[[cols[i]]].rank(ascending=False).applymap( lambda el: round(el + 0.1)) yPos_R = df[[cols[i + 1]]].rank(ascending=False).applymap( lambda el: round(el + 0.1)) yMark_L = df.groupby(cols[i])[cols[i]].mean().dropna() yMark_R = df.groupby(cols[i + 1])[cols[i + 1]].mean().dropna() yMark_L.sort(ascending=False) yMark_R.sort(ascending=False) #print yMark_L labelsL = df.groupby(yPos_L[cols[i]].values)['__label__'].agg( ', '.join) labelsR = df.groupby(yPos_R[cols[i + 1]].values)['__label__'].agg( ', '.join) yPos_L.sort(cols[i], inplace=True) yPos_R.sort(cols[i + 1], inplace=True) yPos_ = yPos_L.join(yPos_R) #.sort(cols[i],inplace=True) # if i == 1: # #print yPos_.T # print labelsL # #yPos_ = df[[cols[i],cols[i+1]]] # # if kind=='stack' : # # yPos_L = df[cols[i]].rank() # yPos_R = df[cols[i+1]].rank() # # labelsL = df.groupby(yPos_L)['__label__'].agg(', '.join) # labelsR = df.groupby(yPos_R)['__label__'].agg(', '.join) # # yPos_ = yPos_L.join(yPos_R) # # yPos_L = labelsL.index.values # yPos_R = labelsR.index.values if kind == "stack": ax.plot([0, 1], [0, 1], color='k', alpha=0.4) else: #print yPos_ lines = ax.plot(yPos_.T, color='k', alpha=0.4) ax.spines['bottom'].set_visible(False) ax.xaxis.set_ticks_position('bottom') if kind == "ordinal": ax.set_ybound(lower=1, upper=len(yPos_)) if kind == "interval": ax.set_ybound(lower=data.min().min(), upper=data.max().max()) #ax.set_xbound(lower=0,upper=1) ax.set_xticklabels([]) #print cols[i] axarr_X[i].set_yticks([1]) axarr_X[i].set_xticklabels([]) axarr_X[i].set_yticklabels([str(cols[i])], fontproperties=font) #ax.set_xticklabels([str(cols[i])],horizontalalignment='center',fontproperties=font) # ax.spines['top'].set_visible(False) # ax.spines['right'].set_visible(False) # ax.spines['left'].set_visible(False) if marker: labelsL_str = [item[1] + (marker % item[0]).rjust(6) for item in zip(yMark_L.values, labelsL.values)] labelsR_str = [(marker % item[0]).ljust(6) + item[1] for item in zip(yMark_R.values, labelsR.values)] ylabelsL_str = map(lambda el: marker % el, yMark_L.values) ylabelsR_str = map(lambda el: marker % el, yMark_R.values) else: labelsL_str = labelsL.values labelsR_str = labelsR.values ylabelsL_str = map(lambda el: u'', yPos_L.values) ylabelsR_str = map(lambda el: u'', yPos_R.values) if i == 0: ax.set_yticks(yPos_L.values) ax.set_yticklabels(labelsL_str, fontproperties=font) elif marker: ax.set_yticks(yPos_L.values) ax.set_yticklabels(ylabelsL_str, fontproperties=font, ha='right' ) #ha='center')#,backgroundcolor='w') else: plt.setp(ax.get_yticklabels(), visible=False) wspace = 0 if i == len(cols) - 2: bx = ax.twinx() bx.set_ybound(ax.get_ybound()) bx.set_yticks(yPos_R.values) bx.set_yticklabels(labelsR_str, fontproperties=font) bx.yaxis.set_tick_params(width=0) bx_X = axarr_X[i].twinx() bx_X.set_xticklabels([]) bx_X.set_yticks([1]) bx_X.yaxis.set_tick_params(width=0) bx_X.set_yticklabels([str(cols[i + 1])], fontproperties=font) if kind == 'ordinal': ax.invert_yaxis() if bx: bx.invert_yaxis() if color: for tl in ax.yaxis.get_ticklabels(): try: for kw, c in color.items(): if kw in tl.get_text(): tl.set_color(c) except: print('fail') pass if bx: for tl in bx.yaxis.get_ticklabels(): try: for kw, c in color.items(): if kw in tl.get_text(): tl.set_color(c) except: pass if color: for kw, c in color.items(): for j, lab__ in enumerate(yPos_.index): if kw in lab__: lines[j].set_color(c) lines[j].set_linewidth(2) lines[j].set_alpha(0.6) for kk, tic_pos in enumerate( ax.yaxis.get_ticklocs()): if yPos_.values[j][0] == tic_pos: ax.yaxis.get_ticklabels()[kk].set_color(c) ax.yaxis.set_tick_params(width=0) ax.xaxis.set_tick_params(width=0) ax.xaxis.grid(False) f.suptitle(title, x=0.5, y=0.02, fontproperties=font) plt.tight_layout() for ax in f.axes: ax.spines['top'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['left'].set_visible(False) tw = ax.yaxis.get_text_widths(renderer)[0] #dpi = f.properties()['dpi'] if wspace == 0: pass else: #wspace = tw/dpi aw = ax.get_tightbbox(renderer).width wspace = tw / aw * 1.4 #f.subplots_adjust(wspace=wspace) f.subplots_adjust(wspace=wspace) if kind == "stack": f.subplots_adjust(wspace=wspace, hspace=0) else: pass if savename: f.savefig(os.path.join('Output', savename), dpi=dpi) #os.system("start " + savename) return f
def slope( data, kind='interval', marker='%0.f', color=None, title='', font_family='GillSans', font_size=12, width=12, height=8, ax=None, savename=None, dpi=150, wspace=None, ): """==== Slope ==== Definition: slope(data,kind=['interval','ordinal'],height,width,font_size,savename,color,title) ---- Plot Slope plot Tufte Style :class:`matplotlib.figure.Figure object`. Parameters ---------- data : pandas dataFrame index indicate the categories columns indicate time / period marker style : str, format Format to present the data default '%0.f' label_position : str ['ordinal', 'interval'] how to position labels. Interval will place them according to their values Ordinal will place them according to their rank font_family : font family name installed on your system font_size : set the font size in case your data have more lines than you can have text lines of text in your figure height, data will be binned to fit (default 12) height : Figure height in inches (default 12) with : Figure width in inches (default 8) savename : file path to save your graph color : a dictionary {label:color} title : a title at the bottom of the graph Examples -------- >>> data = pd.read_csv(os.path.join('Data','EU_GDP_2007_2013.csv'),index_col=0,na_values='-') >>> f = slope(data/1000,kind='interval',height= 12,width=20,font_size=12,savename='EU_interval.png',title = u'title') """ font = FontProperties(font_family) font.set_size(font_size) bx = None df = data.copy() cols = df.columns df['__label__'] = df.index df['__order__'] = range(len(df.index)) if kind == 'stack': f, axarr = plt.subplots(len(df), len(cols) - 1, facecolor="w", squeeze=False, sharex=True) #,sharey=True) else: #f, axarr = plt.subplots(2,len(cols)-1,facecolor="w",squeeze=True,figsize=(width,height),dpi=30)#,sharex=True)#,sharey=True) f = plt.figure(figsize=(width, height), dpi=30, facecolor="w") gs = gridspec.GridSpec( nrows=20, ncols=len(cols) - 1 ) # the 20 rows are just there to provide enought space for the title axarr = [] axarr_X = [] for i in range(len(cols) - 1): axarr.append(plt.subplot(gs[:19, i])) axarr_X.append(plt.subplot(gs[19, i])) axarr = np.array(axarr) axarr_X = np.array(axarr_X) renderer = f.canvas.get_renderer() data_range = [data.min().min(), data.max().max()] fh = f.get_figheight() fw = f.get_figwidth() fdpi = f.get_dpi() nt = fh // (font.get_size() / 72) / 2 res = np.diff(data_range)[0] / nt * 2 if not hasattr(axarr, 'transpose'): axarr = [axarr] for i in range((len(cols) - 1)): ax = axarr[i] axarr_X[i].yaxis.set_tick_params(width=0) axarr_X[i].xaxis.set_tick_params(width=0) """ from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker # orange label obox1 = TextArea("orange - ", textprops=dict(color="k", size=15)) obox2 = TextArea("5 ", textprops=dict(color="b", size=15)) obox3 = TextArea(": ", textprops=dict(color="k", size=15)) obox4 = TextArea("10 ", textprops=dict(color="r", size=15)) orangebox = HPacker(children=[obox1, obox2, obox3, obox4], align="center", pad=0, sep=5) """ if kind == 'interval': labelsL = df.groupby(pd.cut(df[cols[i]], nt))['__label__'].agg( ', '.join).dropna() labelsR = df.groupby(pd.cut(df[cols[i + 1]], nt))['__label__'].agg( ', '.join).dropna() yPos_L = df.groupby(pd.cut(df[cols[i]], nt))[cols[i]].mean().dropna() yPos_R = df.groupby(pd.cut(df[cols[i + 1]], nt))[cols[i + 1]].mean().dropna() yMark_L = df.groupby(pd.cut(df[cols[i]], nt))[cols[i]].mean().dropna() yMark_R = df.groupby(pd.cut(df[cols[i + 1]], nt))[cols[i + 1]].mean().dropna() yPos_ = df[[cols[i], cols[i + 1]]] if kind == 'ordinal': yPos_L = df[[ cols[i] ]].rank(ascending=False).applymap(lambda el: round(el + 0.1)) yPos_R = df[[ cols[i + 1] ]].rank(ascending=False).applymap(lambda el: round(el + 0.1)) yMark_L = df.groupby(cols[i])[cols[i]].mean().dropna() yMark_R = df.groupby(cols[i + 1])[cols[i + 1]].mean().dropna() yMark_L.sort(ascending=False) yMark_R.sort(ascending=False) #print yMark_L labelsL = df.groupby(yPos_L[cols[i]].values)['__label__'].agg( ', '.join) labelsR = df.groupby(yPos_R[cols[i + 1]].values)['__label__'].agg( ', '.join) yPos_L.sort(cols[i], inplace=True) yPos_R.sort(cols[i + 1], inplace=True) yPos_ = yPos_L.join(yPos_R) #.sort(cols[i],inplace=True) # if i == 1: # #print yPos_.T # print labelsL # #yPos_ = df[[cols[i],cols[i+1]]] # # if kind=='stack' : # # yPos_L = df[cols[i]].rank() # yPos_R = df[cols[i+1]].rank() # # labelsL = df.groupby(yPos_L)['__label__'].agg(', '.join) # labelsR = df.groupby(yPos_R)['__label__'].agg(', '.join) # # yPos_ = yPos_L.join(yPos_R) # # yPos_L = labelsL.index.values # yPos_R = labelsR.index.values if kind == "stack": ax.plot([0, 1], [0, 1], color='k', alpha=0.4) else: #print yPos_ lines = ax.plot(yPos_.T, color='k', alpha=0.4) ax.spines['bottom'].set_visible(False) ax.xaxis.set_ticks_position('bottom') if kind == "ordinal": ax.set_ybound(lower=1, upper=len(yPos_)) if kind == "interval": ax.set_ybound(lower=data.min().min(), upper=data.max().max()) #ax.set_xbound(lower=0,upper=1) ax.set_xticklabels([]) #print cols[i] axarr_X[i].set_yticks([1]) axarr_X[i].set_xticklabels([]) axarr_X[i].set_yticklabels([str(cols[i])], fontproperties=font) #ax.set_xticklabels([str(cols[i])],horizontalalignment='center',fontproperties=font) # ax.spines['top'].set_visible(False) # ax.spines['right'].set_visible(False) # ax.spines['left'].set_visible(False) if marker: labelsL_str = [ item[1] + (marker % item[0]).rjust(6) for item in zip(yMark_L.values, labelsL.values) ] labelsR_str = [(marker % item[0]).ljust(6) + item[1] for item in zip(yMark_R.values, labelsR.values)] ylabelsL_str = map(lambda el: marker % el, yMark_L.values) ylabelsR_str = map(lambda el: marker % el, yMark_R.values) else: labelsL_str = labelsL.values labelsR_str = labelsR.values ylabelsL_str = map(lambda el: u'', yPos_L.values) ylabelsR_str = map(lambda el: u'', yPos_R.values) if i == 0: ax.set_yticks(yPos_L.values) ax.set_yticklabels(labelsL_str, fontproperties=font) elif marker: ax.set_yticks(yPos_L.values) ax.set_yticklabels( ylabelsL_str, fontproperties=font, ha='right') #ha='center')#,backgroundcolor='w') else: plt.setp(ax.get_yticklabels(), visible=False) wspace = 0 if i == len(cols) - 2: bx = ax.twinx() bx.set_ybound(ax.get_ybound()) bx.set_yticks(yPos_R.values) bx.set_yticklabels(labelsR_str, fontproperties=font) bx.yaxis.set_tick_params(width=0) bx_X = axarr_X[i].twinx() bx_X.set_xticklabels([]) bx_X.set_yticks([1]) bx_X.yaxis.set_tick_params(width=0) bx_X.set_yticklabels([str(cols[i + 1])], fontproperties=font) if kind == 'ordinal': ax.invert_yaxis() if bx: bx.invert_yaxis() if color: for tl in ax.yaxis.get_ticklabels(): try: for kw, c in color.items(): if kw in tl.get_text(): tl.set_color(c) except: print('fail') pass if bx: for tl in bx.yaxis.get_ticklabels(): try: for kw, c in color.items(): if kw in tl.get_text(): tl.set_color(c) except: pass if color: for kw, c in color.items(): for j, lab__ in enumerate(yPos_.index): if kw in lab__: lines[j].set_color(c) lines[j].set_linewidth(2) lines[j].set_alpha(0.6) for kk, tic_pos in enumerate( ax.yaxis.get_ticklocs()): if yPos_.values[j][0] == tic_pos: ax.yaxis.get_ticklabels()[kk].set_color(c) ax.yaxis.set_tick_params(width=0) ax.xaxis.set_tick_params(width=0) ax.xaxis.grid(False) f.suptitle(title, x=0.5, y=0.02, fontproperties=font) plt.tight_layout() for ax in f.axes: ax.spines['top'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['left'].set_visible(False) tw = ax.yaxis.get_text_widths(renderer)[0] #dpi = f.properties()['dpi'] if wspace == 0: pass else: #wspace = tw/dpi aw = ax.get_tightbbox(renderer).width wspace = tw / aw * 1.4 #f.subplots_adjust(wspace=wspace) f.subplots_adjust(wspace=wspace) if kind == "stack": f.subplots_adjust(wspace=wspace, hspace=0) else: pass if savename: f.savefig(os.path.join('Output', savename), dpi=dpi) #os.system("start " + savename) return f
def slope(data, kind='interval', marker='%0.f', color=None, title='', font_family='GillSans', font_size=12, width=12, height=8, ax=None, savename=None, dpi=150, wspace=None, ): font = FontProperties(font_family) font.set_size(font_size) bx = None df = data.copy() cols = df.columns df['__label__'] = df.index df['__order__'] = range(len(df.index)) if kind == 'stack': f, axarr = plt.subplots(len(df), len(cols) - 1, facecolor="w", squeeze=False, sharex=True) #,sharey=True) else: f = plt.figure(figsize=(width, height), dpi=30, facecolor="w") gs = gridspec.GridSpec( nrows=20, ncols=len(cols) - 1 ) # the 20 rows are just there to provide enought space for the title axarr = [] axarr_X = [] for i in range(len(cols) - 1): axarr.append(plt.subplot(gs[:19, i])) axarr_X.append(plt.subplot(gs[19, i])) axarr = np.array(axarr) axarr_X = np.array(axarr_X) renderer = f.canvas.get_renderer() data_range = [data.min().min(), data.max().max()] fh = f.get_figheight() fw = f.get_figwidth() fdpi = f.get_dpi() nt = fh // (font.get_size() / 72) / 2 res = np.diff(data_range)[0] / nt * 2 if not hasattr(axarr, 'transpose'): axarr = [axarr] for i in range((len(cols) - 1)): ax = axarr[i] axarr_X[i].yaxis.set_tick_params(width=0) axarr_X[i].xaxis.set_tick_params(width=0) """ from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker # orange label obox1 = TextArea("orange - ", textprops=dict(color="k", size=15)) obox2 = TextArea("5 ", textprops=dict(color="b", size=15)) obox3 = TextArea(": ", textprops=dict(color="k", size=15)) obox4 = TextArea("10 ", textprops=dict(color="r", size=15)) orangebox = HPacker(children=[obox1, obox2, obox3, obox4], align="center", pad=0, sep=5) """ if kind == 'interval': labelsL = df.groupby(pd.cut(df[cols[i]], nt))['__label__'].agg( ', '.join).dropna() labelsR = df.groupby(pd.cut(df[cols[i + 1]], nt))['__label__'].agg( ', '.join).dropna() yPos_L = df.groupby(pd.cut(df[cols[i]], nt))[cols[i]].mean().dropna() yPos_R = df.groupby(pd.cut(df[cols[i + 1]], nt))[cols[i + 1]].mean().dropna() yMark_L = df.groupby(pd.cut(df[cols[i]], nt))[cols[i]].mean().dropna() yMark_R = df.groupby(pd.cut(df[cols[i + 1]], nt))[cols[i + 1]].mean().dropna() yPos_ = df[[cols[i], cols[i + 1]]] if kind == 'ordinal': yPos_L = df[[cols[i]]].rank(ascending=False).applymap( lambda el: round(el + 0.1)) yPos_R = df[[cols[i + 1]]].rank(ascending=False).applymap( lambda el: round(el + 0.1)) yMark_L = df.groupby(cols[i])[cols[i]].mean().dropna() yMark_R = df.groupby(cols[i + 1])[cols[i + 1]].mean().dropna() yMark_L.sort(ascending=False) yMark_R.sort(ascending=False) #print yMark_L labelsL = df.groupby(yPos_L[cols[i]].values)['__label__'].agg( ', '.join) labelsR = df.groupby(yPos_R[cols[i + 1]].values)['__label__'].agg( ', '.join) yPos_L.sort(cols[i], inplace=True) yPos_R.sort(cols[i + 1], inplace=True) yPos_ = yPos_L.join(yPos_R) #.sort(cols[i],inplace=True) # if i == 1: # #print yPos_.T # print labelsL # #yPos_ = df[[cols[i],cols[i+1]]] # # if kind=='stack' : # # yPos_L = df[cols[i]].rank() # yPos_R = df[cols[i+1]].rank() # # labelsL = df.groupby(yPos_L)['__label__'].agg(', '.join) # labelsR = df.groupby(yPos_R)['__label__'].agg(', '.join) # # yPos_ = yPos_L.join(yPos_R) # # yPos_L = labelsL.index.values # yPos_R = labelsR.index.values if kind == "stack": ax.plot([0, 1], [0, 1], color='k', alpha=0.4) else: #print yPos_ lines = ax.plot(yPos_.T, color='k', alpha=0.4) ax.spines['bottom'].set_visible(False) ax.xaxis.set_ticks_position('bottom') if kind == "ordinal": ax.set_ybound(lower=1, upper=len(yPos_)) if kind == "interval": ax.set_ybound(lower=data.min().min(), upper=data.max().max()) #ax.set_xbound(lower=0,upper=1) ax.set_xticklabels([]) #print cols[i] axarr_X[i].set_yticks([1]) axarr_X[i].set_xticklabels([]) axarr_X[i].set_yticklabels([str(cols[i])], fontproperties=font) if marker: labelsL_str = [item[1] + (marker % item[0]).rjust(6) for item in zip(yMark_L.values, labelsL.values)] labelsR_str = [(marker % item[0]).ljust(6) + item[1] for item in zip(yMark_R.values, labelsR.values)] ylabelsL_str = map(lambda el: marker % el, yMark_L.values) ylabelsR_str = map(lambda el: marker % el, yMark_R.values) else: labelsL_str = labelsL.values labelsR_str = labelsR.values ylabelsL_str = map(lambda el: u'', yPos_L.values) ylabelsR_str = map(lambda el: u'', yPos_R.values) if i == 0: ax.set_yticks(yPos_L.values) ax.set_yticklabels(labelsL_str, fontproperties=font) elif marker: ax.set_yticks(yPos_L.values) ax.set_yticklabels([el for el in ylabelsL_str], fontproperties=font, ha='right' ) #ha='center')#,backgroundcolor='w') else: plt.setp(ax.get_yticklabels(), visible=False) wspace = 0 if i == len(cols) - 2: bx = ax.twinx() bx.set_ybound(ax.get_ybound()) bx.set_yticks(yPos_R.values) bx.set_yticklabels(labelsR_str, fontproperties=font) bx.yaxis.set_tick_params(width=0) bx_X = axarr_X[i].twinx() bx_X.set_xticklabels([]) bx_X.set_yticks([1]) bx_X.yaxis.set_tick_params(width=0) bx_X.set_yticklabels([str(cols[i + 1])], fontproperties=font) if kind == 'ordinal': ax.invert_yaxis() if bx: bx.invert_yaxis() if color: for tl in ax.yaxis.get_ticklabels(): try: for kw, c in color.items(): if kw in tl.get_text(): tl.set_color(c) except: print('fail') pass if bx: for tl in bx.yaxis.get_ticklabels(): try: for kw, c in color.items(): if kw in tl.get_text(): tl.set_color(c) except: pass if color: for kw, c in color.items(): for j, lab__ in enumerate(yPos_.index): if kw in lab__: lines[j].set_color(c) lines[j].set_linewidth(2) lines[j].set_alpha(0.6) for kk, tic_pos in enumerate( ax.yaxis.get_ticklocs()): if yPos_.values[j][0] == tic_pos: ax.yaxis.get_ticklabels()[kk].set_color(c) ax.yaxis.set_tick_params(width=0) ax.xaxis.set_tick_params(width=0) ax.xaxis.grid(False) f.suptitle(title, x=0.5, y=0.02, fontproperties=font) plt.tight_layout() for ax in f.axes: ax.spines['top'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['left'].set_visible(False) tw = ax.yaxis.get_text_widths(renderer)[0] if wspace == 0: pass else: #wspace = tw/dpi aw = ax.get_tightbbox(renderer).width wspace = tw / aw * 1.4 f.subplots_adjust(wspace=wspace) if kind == "stack": f.subplots_adjust(wspace=wspace, hspace=0) else: pass if savename: f.savefig( savename, dpi=dpi) return f
def slope( data, kind='interval', marker='%0.f', color=None, title='', font_family='GillSans', font_size=12, width=12, height=8, ax=None, savename=None, dpi=150, wspace=None, ): font = FontProperties(font_family) font.set_size(font_size) bx = None df = data.copy() cols = df.columns df['__label__'] = df.index df['__order__'] = range(len(df.index)) if kind == 'stack': f, axarr = plt.subplots(len(df), len(cols) - 1, facecolor="w", squeeze=False, sharex=True) #,sharey=True) else: f = plt.figure(figsize=(width, height), dpi=30, facecolor="w") gs = gridspec.GridSpec( nrows=20, ncols=len(cols) - 1 ) # the 20 rows are just there to provide enought space for the title axarr = [] axarr_X = [] for i in range(len(cols) - 1): axarr.append(plt.subplot(gs[:19, i])) axarr_X.append(plt.subplot(gs[19, i])) axarr = np.array(axarr) axarr_X = np.array(axarr_X) renderer = f.canvas.get_renderer() data_range = [data.min().min(), data.max().max()] fh = f.get_figheight() fw = f.get_figwidth() fdpi = f.get_dpi() nt = fh // (font.get_size() / 72) / 2 res = np.diff(data_range)[0] / nt * 2 if not hasattr(axarr, 'transpose'): axarr = [axarr] for i in range((len(cols) - 1)): ax = axarr[i] axarr_X[i].yaxis.set_tick_params(width=0) axarr_X[i].xaxis.set_tick_params(width=0) """ from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker # orange label obox1 = TextArea("orange - ", textprops=dict(color="k", size=15)) obox2 = TextArea("5 ", textprops=dict(color="b", size=15)) obox3 = TextArea(": ", textprops=dict(color="k", size=15)) obox4 = TextArea("10 ", textprops=dict(color="r", size=15)) orangebox = HPacker(children=[obox1, obox2, obox3, obox4], align="center", pad=0, sep=5) """ if kind == 'interval': labelsL = df.groupby(pd.cut(df[cols[i]], nt))['__label__'].agg( ', '.join).dropna() labelsR = df.groupby(pd.cut(df[cols[i + 1]], nt))['__label__'].agg( ', '.join).dropna() yPos_L = df.groupby(pd.cut(df[cols[i]], nt))[cols[i]].mean().dropna() yPos_R = df.groupby(pd.cut(df[cols[i + 1]], nt))[cols[i + 1]].mean().dropna() yMark_L = df.groupby(pd.cut(df[cols[i]], nt))[cols[i]].mean().dropna() yMark_R = df.groupby(pd.cut(df[cols[i + 1]], nt))[cols[i + 1]].mean().dropna() yPos_ = df[[cols[i], cols[i + 1]]] if kind == 'ordinal': yPos_L = df[[ cols[i] ]].rank(ascending=False).applymap(lambda el: round(el + 0.1)) yPos_R = df[[ cols[i + 1] ]].rank(ascending=False).applymap(lambda el: round(el + 0.1)) yMark_L = df.groupby(cols[i])[cols[i]].mean().dropna() yMark_R = df.groupby(cols[i + 1])[cols[i + 1]].mean().dropna() yMark_L.sort(ascending=False) yMark_R.sort(ascending=False) #print yMark_L labelsL = df.groupby(yPos_L[cols[i]].values)['__label__'].agg( ', '.join) labelsR = df.groupby(yPos_R[cols[i + 1]].values)['__label__'].agg( ', '.join) yPos_L.sort(cols[i], inplace=True) yPos_R.sort(cols[i + 1], inplace=True) yPos_ = yPos_L.join(yPos_R) #.sort(cols[i],inplace=True) # if i == 1: # #print yPos_.T # print labelsL # #yPos_ = df[[cols[i],cols[i+1]]] # # if kind=='stack' : # # yPos_L = df[cols[i]].rank() # yPos_R = df[cols[i+1]].rank() # # labelsL = df.groupby(yPos_L)['__label__'].agg(', '.join) # labelsR = df.groupby(yPos_R)['__label__'].agg(', '.join) # # yPos_ = yPos_L.join(yPos_R) # # yPos_L = labelsL.index.values # yPos_R = labelsR.index.values if kind == "stack": ax.plot([0, 1], [0, 1], color='k', alpha=0.4) else: #print yPos_ lines = ax.plot(yPos_.T, color='k', alpha=0.4) ax.spines['bottom'].set_visible(False) ax.xaxis.set_ticks_position('bottom') if kind == "ordinal": ax.set_ybound(lower=1, upper=len(yPos_)) if kind == "interval": ax.set_ybound(lower=data.min().min(), upper=data.max().max()) #ax.set_xbound(lower=0,upper=1) ax.set_xticklabels([]) #print cols[i] axarr_X[i].set_yticks([1]) axarr_X[i].set_xticklabels([]) axarr_X[i].set_yticklabels([str(cols[i])], fontproperties=font) if marker: labelsL_str = [ item[1] + (marker % item[0]).rjust(6) for item in zip(yMark_L.values, labelsL.values) ] labelsR_str = [(marker % item[0]).ljust(6) + item[1] for item in zip(yMark_R.values, labelsR.values)] ylabelsL_str = map(lambda el: marker % el, yMark_L.values) ylabelsR_str = map(lambda el: marker % el, yMark_R.values) else: labelsL_str = labelsL.values labelsR_str = labelsR.values ylabelsL_str = map(lambda el: u'', yPos_L.values) ylabelsR_str = map(lambda el: u'', yPos_R.values) if i == 0: ax.set_yticks(yPos_L.values) ax.set_yticklabels(labelsL_str, fontproperties=font) elif marker: ax.set_yticks(yPos_L.values) ax.set_yticklabels( [el for el in ylabelsL_str], fontproperties=font, ha='right') #ha='center')#,backgroundcolor='w') else: plt.setp(ax.get_yticklabels(), visible=False) wspace = 0 if i == len(cols) - 2: bx = ax.twinx() bx.set_ybound(ax.get_ybound()) bx.set_yticks(yPos_R.values) bx.set_yticklabels(labelsR_str, fontproperties=font) bx.yaxis.set_tick_params(width=0) bx_X = axarr_X[i].twinx() bx_X.set_xticklabels([]) bx_X.set_yticks([1]) bx_X.yaxis.set_tick_params(width=0) bx_X.set_yticklabels([str(cols[i + 1])], fontproperties=font) if kind == 'ordinal': ax.invert_yaxis() if bx: bx.invert_yaxis() if color: for tl in ax.yaxis.get_ticklabels(): try: for kw, c in color.items(): if kw in tl.get_text(): tl.set_color(c) except: print('fail') pass if bx: for tl in bx.yaxis.get_ticklabels(): try: for kw, c in color.items(): if kw in tl.get_text(): tl.set_color(c) except: pass if color: for kw, c in color.items(): for j, lab__ in enumerate(yPos_.index): if kw in lab__: lines[j].set_color(c) lines[j].set_linewidth(2) lines[j].set_alpha(0.6) for kk, tic_pos in enumerate( ax.yaxis.get_ticklocs()): if yPos_.values[j][0] == tic_pos: ax.yaxis.get_ticklabels()[kk].set_color(c) ax.yaxis.set_tick_params(width=0) ax.xaxis.set_tick_params(width=0) ax.xaxis.grid(False) f.suptitle(title, x=0.5, y=0.02, fontproperties=font) plt.tight_layout() for ax in f.axes: ax.spines['top'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['left'].set_visible(False) tw = ax.yaxis.get_text_widths(renderer)[0] if wspace == 0: pass else: #wspace = tw/dpi aw = ax.get_tightbbox(renderer).width wspace = tw / aw * 1.4 f.subplots_adjust(wspace=wspace) if kind == "stack": f.subplots_adjust(wspace=wspace, hspace=0) else: pass if savename: f.savefig(savename, dpi=dpi) return f
class Chart: def __init__(self, props, subdefaults): self.file = None self.filename = None self.props = { "imageType": "png", # Output image type. "dpi": 72, # Image DPI resolution. "width": 800, # Output image width in pixels (vs. DPI). "height": 600, # Output image height in pixels (vs. DPI). "padding": 50, # Padding around the figure edge, in pixels. "textPadding": 3, # Padding around text, in pixels. "fontFamily": "sans-serif", # Font family. "fontName": "Luxi Sans", # Font name. "fontSize": 12, # Size of non-title text, in pixels. "titleFontName": "Bitstream Vera Sans", "titleFontSize": 18, # Size of title text, in pixels. "subtitleFontSize": 14, # Size of subtitle text, in pixels. "axtitleFontSize": 16, # Size of axis title text, in pixels. "xAxisScale": "lin", # X axis scale, lin or log. "yAxisScale": "lin", # Y axis scale, lin or log. "square": False, # Force square layout. "integral": False, #force integral display on legend "notitle": False, #suppress title "nolabels": False, #suppress axis labels "sort":False, #sort items and legend entries by value "max_legend":100 #maximum items in the legend } for (k, v) in subdefaults.iteritems(): self.props[k] = v for (k, v) in props.iteritems(): self.props[k] = v self.font = FontProperties() self.font.set_family(self.get('fontFamily')) self.font.set_name(self.get('fontName')) self.font.set_size(float(self.get('fontSize'))) self.tfont = FontProperties() self.tfont.set_family(self.get('titleFontFamily', self.font.get_family()[-1])) self.tfont.set_name(self.get('titleFontName', self.font.get_name())) self.tfont.set_size(self.get('titleFontSize', self.font.get_size())) self.tfont.set_weight('bold') self.sfont = FontProperties() self.sfont.set_family(self.get('subtitleFontFamily', self.tfont.get_family()[-1])) self.sfont.set_name(self.get('subtitleFontName', self.tfont.get_name())) self.sfont.set_size(self.get('subtitleFontSize', self.tfont.get_size())) self.afont = FontProperties() self.afont.set_family(self.get('axtitleFontFamily', self.tfont.get_family()[-1])) self.afont.set_name(self.get('axtitleFontName', self.tfont.get_name())) self.afont.set_size(self.get('axtitleFontSize', self.tfont.get_size())) self.afont.set_weight('bold') def __del__(self): if self.file != None: os.close(self.file) def get(self, key, default=None): return getattr(self, key, self.props.get(key, default)) def draw(self): (fig, canvas, w, h) = self.canvas() fig.text(.5, .5, "No data.", horizontalalignment='center', fontproperties=self.font) return self.save(fig, canvas) def legend(self): (fig, canvas, w, h) = self.canvas() fig.text(.5, .5, "No legend.", horizontalalignment='center', fontproperties=self.font) return self.save(fig, canvas) def details(self): return {} def canvas(self): type = self.get("imageType", "png") fig = Figure() if type == "png": canvas = FigureCanvasAgg(fig) (self.file, self.filename) = mkstemp(".%s" % type) elif type == "svg": canvas = FigureCanvasSVG(fig) (self.file, self.filename) = mkstemp(".%s" % type) elif type == "pdf": canvas = FigureCanvasPdf(fig) (self.file, self.filename) = mkstemp(".%s" % type) elif type == "ps" or type == "eps": canvas = FigureCanvasPS(fig) (self.file, self.filename) = mkstemp(".%s" % type) else: raise "Invalid render target requested" # Set basic figure parameters dpi = float(self.get('dpi')) (w, h) = (float(self.get('width')), float(self.get('height'))) (win, hin) = (w/dpi, h/dpi) fig.set_size_inches(win, hin) fig.set_dpi(dpi) fig.set_facecolor('white') return (fig, canvas, w, h) def save(self, fig, canvas): canvas.draw() if not self.filename: canvas.print_figure(self.file, dpi=float(self.get('dpi'))) return self.file else: canvas.print_figure(self.filename, dpi=float(self.get('dpi'))) f = file(self.filename, "r") # PS backend writes over the file os.remove(self.filename) # return os.fdopen(self.file) os.close(self.file) self.file = None self.filename = None return f def prepare(self): # Create canvas and determine figure parameters (fig, canvas, w, h) = self.canvas() dpif = float(self.get('dpi')) / 72 padding = float(self.get('padding')) * dpif / h textPadding = float(self.get('textPadding')) * dpif titleFontSize = float(self.get('titleFontSize')) axFontSize = float(self.get('axtitleFontSize')) subFontSize = float(self.get('subtitleFontSize')) title = self.get("title", "").split("\n") if not self.get("notitle",False): hsub = (len(title)-1) * (subFontSize * dpif + 4) + textPadding htitle = hsub + titleFontSize * dpif + textPadding * 2 else: hsub = 0 htitle = 0 if self.get("nolabels",False): padding = 0 # Configure axes if self.get('square'): minsize = 1 - 2*padding axrect = (.5 - minsize/2 * h/w, padding, h/w * minsize, minsize) else: axrect = (padding, padding, 1 - 1.25*padding, 1 - htitle/h - padding) ax = fig.add_axes(axrect) #frame = ax.get_frame() #frame.set_fill(False) xlog = (str(self.get('xAxisScale', "lin")) == 'log') ylog = (str(self.get('yAxisScale', "lin")) == 'log') if xlog: ax.semilogx() if ylog: ax.semilogy() setp(ax.get_xticklabels(), fontproperties=self.font) setp(ax.get_yticklabels(), fontproperties=self.font) setp(ax.get_xticklines(), markeredgewidth=2.0, zorder=4.0) setp(ax.get_yticklines(), markeredgewidth=2.0) ax.grid(True, alpha=0.25, color='#000000', linewidth=0.1) # Set titles if not self.get("notitle",False): ax.title = ax.text(.5, 1+(hsub+textPadding)/(axrect[-1]*h), title[0], verticalalignment='bottom', horizontalalignment='center', transform=ax.transAxes, clip_box=None, fontproperties=self.tfont) ax._set_artist_props(ax.title) if len(title) > 1: ax.subtitle = ax.text(.5, 1+textPadding/(axrect[-1]*h), "\n".join(title[1:]), verticalalignment='bottom', horizontalalignment='center', transform=ax.transAxes, clip_box=None, fontproperties=self.sfont) if not self.get("nolabels",False): ax.set_xlabel(self.get("xAxisTitle", ""), fontproperties=self.afont) ax.set_ylabel(self.get("yAxisTitle", ""), fontproperties=self.afont) return (fig, canvas, ax) def map(self): return '' def make(self): img = self.draw().read() legend = self.legend().read() map = self.map() return img,legend,map