def _wrap(self, subset=None, axis=0): subset = pd.IndexSlice[:, :] if subset is None else subset subset = non_reducing_slice(subset) if axis in [0, "columns"]: idx = self._current_index(subset)[1] rename = dict( zip( self.display_data.columns[idx], self._wrap_iterable(self.display_data.columns[idx]), ) ) self.display_data.rename(columns=rename, inplace=True) elif axis in [1, "index"]: idx = self._current_index(subset)[0] rename = dict( zip( self.display_data.index[idx], self._wrap_iterable(self.display_data.index[idx]), ) ) self.display_data.rename(index=rename, inplace=True) else: raise ValueError(f"unknown value for axis: {axis}") return self
def test_list_slice(self): # like dataframe getitem slices = [["A"], Series(["A"]), np.array(["A"])] df = DataFrame({"A": [1, 2], "B": [3, 4]}, index=["A", "B"]) expected = pd.IndexSlice[:, ["A"]] for subset in slices: result = non_reducing_slice(subset) tm.assert_frame_equal(df.loc[result], df.loc[expected])
def test_list_slice(self, box): # like dataframe getitem subset = box(["A"]) df = DataFrame({"A": [1, 2], "B": [3, 4]}, index=["A", "B"]) expected = pd.IndexSlice[:, ["A"]] result = non_reducing_slice(subset) tm.assert_frame_equal(df.loc[result], df.loc[expected])
def emojify(self, subset=None): subset = pd.IndexSlice[:, :] if subset is None else subset subset = non_reducing_slice(subset) idx = self._current_index(subset=subset) result = self.display_data.iloc[idx].applymap(emoji.emojize) self.display_data.iloc[idx] = result.values return self
def _current_index(self, subset): subset = pd.IndexSlice[:, :] if subset is None else subset subset = non_reducing_slice(subset) selected = self.data.loc[subset] idx_slice = pd.IndexSlice[ self.data.index.get_indexer(selected.index), self.data.columns.get_indexer(selected.columns), ] return idx_slice
def test_non_reducing_multi_slice_on_multiindex(self, slice_): # GH 33562 cols = pd.MultiIndex.from_product([["a", "b"], ["c", "d"], ["e", "f"]]) idxs = pd.MultiIndex.from_product([["U", "V"], ["W", "X"], ["Y", "Z"]]) df = DataFrame(np.arange(64).reshape(8, 8), columns=cols, index=idxs) expected = df.loc[slice_] result = df.loc[non_reducing_slice(slice_)] tm.assert_frame_equal(result, expected)
def get_heatmap(self, cmap, sub=None, text_color_threshold=0.408): if sub is None: sub = self.subset cmap = self.min_max_scaler(sub).applymap( lambda x: self.get_heatmap_color(x, cmap, text_color_threshold)) sub = maybe_numeric_slice(self.data, sub) sub = non_reducing_slice(sub) c_mapping = lambda x: cmap.loc[sub] self.apply(c_mapping, subset=sub, axis=None) return self
def _convert_to_image(self, subset=None, height=30): subset = pd.IndexSlice[:, :] if subset is None else subset subset = non_reducing_slice(subset) self.display_data.loc[subset] = ( f'<div style="height:{height}px;object-fit:contain;"><img src="' + self.data.loc[subset].astype(str) + '" style="height:100%;width:100%;object-fit:contain;"/></div>' ) return self
def emoji_score(self, subset=None, emoji_str=None, bins=None, axis=0): subset = pd.IndexSlice[:, :] if subset is None else subset subset = non_reducing_slice(subset) idx = self._current_index(subset=subset) result = self.display_data.iloc[idx].apply( self._emoji_score, axis=axis, result_type="expand", args=(emoji_str, bins) ) self.display_data.iloc[idx] = result.values return self.align(subset=subset, location="left", axis=axis)
def to_precision_str(self, subset=None, precision=0, include_zero=True): subset = pd.IndexSlice[:, :] if subset is None else subset subset = non_reducing_slice(subset) def precision_str(x, precision=precision): if (include_zero or x > 0) and x <= 10 ** -precision: return f"<{10**-precision}" else: return f"{{0:.{precision}f}}".format(x) self.display_data.loc[subset] = self.data.loc[subset].applymap(precision_str) return self
def test_non_reducing_slice_on_multiindex(self): # GH 19861 dic = { ("a", "d"): [1, 4], ("a", "c"): [2, 3], ("b", "c"): [3, 2], ("b", "d"): [4, 1], } df = DataFrame(dic, index=[0, 1]) idx = pd.IndexSlice slice_ = idx[:, idx["b", "d"]] tslice_ = non_reducing_slice(slice_) result = df.loc[tslice_] expected = DataFrame({("b", "d"): [4, 1]}) tm.assert_frame_equal(result, expected)
def _tooltip(self, tip, subset=None, part=None): subset = pd.IndexSlice[:, :] if subset is None else subset subset = non_reducing_slice(subset) if part is None: part = "data" if part == "data": self.display_data.loc[subset] = ( "<div title='" + tip + "'>" + self.display_data.loc[subset].astype(str) + "</div>" ) elif part == "columns": idx = self._current_index(subset)[1] rename = dict( zip( self.display_data.columns[idx], "<div title='" + tip + "'>" + self.display_data.columns[idx].astype(str) + "</div>", ) ) self.display_data.rename(columns=rename, inplace=True) elif part == "index": idx = self._current_index(subset)[0] rename = dict( zip( self.display_data.index[idx], "<div title='" + tip + "'>" + self.display_data.index[idx].astype(str) + "</div>", ) ) self.display_data.rename(index=rename, inplace=True) else: raise ValueError(f"unknown value for part: {part}") return self
def scaled_background_gradient( self, subset=None, cmap="RdBu_r", low=0, high=0, center_zero=False, vmin=None, vmax=None, ): if center_zero: sub = pd.IndexSlice[:, :] if subset is None else subset sub = non_reducing_slice(sub) vmax = ( self.data.loc[sub] .replace({np.inf: np.nan, -np.inf: np.nan}) .max(skipna=True) .max() if vmax is None else vmax ) vmin = ( self.data.loc[sub] .replace({np.inf: np.nan, -np.inf: np.nan}) .min(skipna=True) .min() if vmin is None else vmin ) vmax = max(abs(vmax), abs(vmin)) vmin = -vmax r = self.background_gradient( subset=subset, cmap=cmap, vmin=vmin, vmax=vmax, low=low, high=high, ) return r
def test_non_reducing_slice(self, slc): df = DataFrame([[0, 1], [2, 3]]) tslice_ = non_reducing_slice(slc) assert isinstance(df.loc[tslice_], DataFrame)
def _circle( self, subset=None, show_text=True, color=None, cmap=None, vmin=None, vmax=None, scale=False, size=25, min_size=5, morph=False, ): subset = pd.IndexSlice[:, :] if subset is None else subset subslice = non_reducing_slice(subset) if color: palette = sns.color_palette([color]) # print(palette) elif cmap is None: palette = sns.light_palette((210, 90, 60), input="husl", n_colors=10) else: # if isinstance(palette, str): palette = sns.color_palette(cmap) # Make sure we don't select text columns if len(palette) > 1: subslice = pd.IndexSlice[ self.data.loc[subslice].index, self.data.loc[subslice].select_dtypes(exclude=["object"]).columns, ] idx = self._current_index(subslice) self.circle_styles = self.circle_styles or [] circle_id = len(self.circle_styles) + 1 props = [ ("height", f"{size}px"), ("width", f"{size}px"), ("border-radius", "50%"), ("color", "#000"), ("line-height", f"{size}px"), ("display", "inline-block"), ("text-align", "center"), ("vertical-align", "middle"), ] self.circle_styles.append({"name": f"circle{circle_id}", "props": props}) self.palette_styles = self.palette_styles or [] for i, color in enumerate(palette.as_hex()): props = [("background-color", color)] if scale: circle_size = min_size + ((size - min_size) / len(palette) * (i + 1)) props += [ ("height", f"{circle_size}px"), ("width", f"{circle_size}px"), ("line-height", f"{circle_size}px"), ("text-align", "center"), ] if morph: props += [("border-radius", f"{50 - int(50 / len(palette)) * i}%")] self.palette_styles.append( {"name": f"color{circle_id}_{i}", "props": props} ) if len(palette) > 1: vmax = ( self.data.loc[subslice].max().max() * 1.01 if vmax is None else vmax * 1.01 ) text = self.display_data.iloc[idx].astype(str) if show_text else "" self.display_data.iloc[idx] = ( f"<div class='circle{circle_id} color{circle_id}_" + (self.data.loc[subslice] / (vmax / len(palette))) .astype(int) .astype(str) + "'>" + text + "</div>" ) else: text = self.display_data.iloc[idx].astype(str) if show_text else "" self.display_data.iloc[idx] = ( f"<div class='circle{circle_id} color{circle_id}_0'>" + text + "</div>" ) return self