def compute_layout(self, data): if not self.rows and not self.cols: return layout_null() base_rows = combine_vars(data, self.plot.environment, self.rows, drop=self.drop) if not self.as_table: # Reverse the order of the rows base_rows = base_rows[::-1] base_cols = combine_vars(data, self.plot.environment, self.cols, drop=self.drop) base = cross_join(base_rows, base_cols) if self.margins: base = add_margins(base, [self.rows, self.cols], self.margins) base = base.drop_duplicates().reset_index(drop=True) n = len(base) panel = ninteraction(base, drop=True) panel = pd.Categorical(panel, categories=range(1, n + 1)) if self.rows: rows = ninteraction(base[self.rows], drop=True) else: rows = 1 if self.cols: cols = ninteraction(base[self.cols], drop=True) else: cols = 1 layout = pd.DataFrame({'PANEL': panel, 'ROW': rows, 'COL': cols}) layout = pd.concat([layout, base], axis=1) layout = layout.sort_values('PANEL') layout.reset_index(drop=True, inplace=True) # Relax constraints, if necessary layout['SCALE_X'] = layout['COL'] if self.free['x'] else 1 layout['SCALE_Y'] = layout['ROW'] if self.free['y'] else 1 layout['AXIS_X'] = layout['ROW'] == layout['ROW'].max() layout['AXIS_Y'] = layout['COL'] == layout['COL'].min() self.nrow = layout['ROW'].max() self.ncol = layout['COL'].max() return layout
def test_add_margins(): df = mtcars.loc[:, ['mpg', 'disp', 'vs', 'am', 'gear']] n = len(df) all_lst = ['(all)'] * n vars = [('vs', 'am'), ('gear',)] dfx = add_margins(df, vars, True) assert(dfx['vs'].dtype == 'category') assert(dfx['am'].dtype == 'category') assert(dfx['gear'].dtype == 'category') # What we expect, where each row is of # column length n # # mpg disp vs am gear # --- ---- -- -- ---- # * * * * * # * * (all) (all) * # * * * (all) * # * * * * (all) # * * (all) (all) (all) # * * * (all) (all) assert(all(dfx.loc[0:n-1, 'am'] != all_lst)) assert(all(dfx.loc[0:n-1, 'vs'] != all_lst)) assert(all(dfx.loc[0:n-1, 'gear'] != all_lst)) assert(all(dfx.loc[n:2*n-1, 'vs'] == all_lst)) assert(all(dfx.loc[n:2*n-1, 'am'] == all_lst)) assert(all(dfx.loc[2*n:3*n-1, 'am'] == all_lst)) assert(all(dfx.loc[3*n:4*n-1, 'gear'] == all_lst)) assert(all(dfx.loc[4*n:5*n-1, 'am'] == all_lst)) assert(all(dfx.loc[4*n:5*n-1, 'vs'] == all_lst)) assert(all(dfx.loc[4*n:5*n-1, 'gear'] == all_lst)) assert(all(dfx.loc[5*n:6*n-1, 'am'] == all_lst)) assert(all(dfx.loc[5*n:6*n-1, 'gear'] == all_lst))
def test_add_margins(): df = mtcars.loc[:, ['mpg', 'disp', 'vs', 'am', 'gear']] n = len(df) all_lst = ['(all)'] * n vars = [('vs', 'am'), ('gear', )] dfx = add_margins(df, vars, True) assert (dfx['vs'].dtype == 'category') assert (dfx['am'].dtype == 'category') assert (dfx['gear'].dtype == 'category') # What we expect, where each row is of # column length n # # mpg disp vs am gear # --- ---- -- -- ---- # * * * * * # * * (all) (all) * # * * * (all) * # * * * * (all) # * * (all) (all) (all) # * * * (all) (all) assert (all(dfx.loc[0:n - 1, 'am'] != all_lst)) assert (all(dfx.loc[0:n - 1, 'vs'] != all_lst)) assert (all(dfx.loc[0:n - 1, 'gear'] != all_lst)) assert (all(dfx.loc[n:2 * n - 1, 'vs'] == all_lst)) assert (all(dfx.loc[n:2 * n - 1, 'am'] == all_lst)) assert (all(dfx.loc[2 * n:3 * n - 1, 'am'] == all_lst)) assert (all(dfx.loc[3 * n:4 * n - 1, 'gear'] == all_lst)) assert (all(dfx.loc[4 * n:5 * n - 1, 'am'] == all_lst)) assert (all(dfx.loc[4 * n:5 * n - 1, 'vs'] == all_lst)) assert (all(dfx.loc[4 * n:5 * n - 1, 'gear'] == all_lst)) assert (all(dfx.loc[5 * n:6 * n - 1, 'am'] == all_lst)) assert (all(dfx.loc[5 * n:6 * n - 1, 'gear'] == all_lst))
def map(self, data, layout): if not len(data): data['PANEL'] = pd.Categorical( [], categories=layout['PANEL'].cat.categories, ordered=True) return data vars = [x for x in self.rows + self.cols] margin_vars = [ list(data.columns & self.rows), list(data.columns & self.cols) ] data = add_margins(data, margin_vars, self.margins) facet_vals = eval_facet_vars(data, vars, self.plot.environment) data, facet_vals = add_missing_facets(data, layout, vars, facet_vals) # assign each point to a panel if len(facet_vals) == 0: # Special case of no facetting data['PANEL'] = 1 else: keys = join_keys(facet_vals, layout, vars) data['PANEL'] = match(keys['x'], keys['y'], start=1) data = data.sort_values('PANEL', kind='mergesort') # matching dtype and # the categories(panel numbers) for the data should be in the # same order as the panels. i.e the panels are the reference, # they "know" the right order data['PANEL'] = pd.Categorical( data['PANEL'], categories=layout['PANEL'].cat.categories, ordered=True) data.reset_index(drop=True, inplace=True) return data