Source code for plotnine.coords.coord_flip
from __future__ import annotations
import typing
import pandas as pd
from ..iapi import labels_view, panel_ranges, panel_view
from .coord_cartesian import coord_cartesian
if typing.TYPE_CHECKING:
from typing import TypeVar
from plotnine.typing import Scale
THasLabels = TypeVar(
"THasLabels", bound=pd.DataFrame | labels_view | panel_view
)
[docs]class coord_flip(coord_cartesian):
"""
Flipped cartesian coordinates
The horizontal becomes vertical, and vertical becomes
horizontal. This is primarily useful for converting
geoms and statistics which display y conditional
on x, to x conditional on y.
Parameters
----------
xlim : None | (float, float)
Limits for x axis. If None, then they are
automatically computed.
ylim : None | (float, float)
Limits for y axis. If None, then they are
automatically computed.
expand : bool
If `True`, expand the coordinate axes by
some factor. If `False`, use the limits
from the data.
"""
def labels(self, cur_labels: labels_view) -> labels_view:
return flip_labels(super().labels(cur_labels))
def transform(
self, data: pd.DataFrame, panel_params: panel_view, munch: bool = False
) -> pd.DataFrame:
data = flip_labels(data)
return super().transform(data, panel_params, munch=munch)
def setup_panel_params(self, scale_x: Scale, scale_y: Scale) -> panel_view:
panel_params = super().setup_panel_params(scale_x, scale_y)
return flip_labels(panel_params)
def setup_layout(self, layout: pd.DataFrame) -> pd.DataFrame:
# switch the scales
x, y = "SCALE_X", "SCALE_Y"
layout[x], layout[y] = layout[y].copy(), layout[x].copy()
return layout
def range(self, panel_params: panel_view) -> panel_ranges:
"""
Return the range along the dimensions of the coordinate system
"""
# Defaults to providing the 2D x-y ranges
return panel_ranges(x=panel_params.y.range, y=panel_params.x.range)
def flip_labels(obj: THasLabels) -> THasLabels:
"""
Rename fields x to y and y to x
Parameters
----------
obj : dict_like | dataclass
Object with labels to rename
"""
def sub(a: str, b: str, df: pd.DataFrame):
"""
Substitute all keys that start with a to b
"""
columns: list[str] = df.columns.tolist()
for label in columns:
if label.startswith(a):
new_label = b + label[1:]
df[new_label] = df.pop(label)
# TODO: pyright cannot handle
# isinstance(obj, (labels_view, panel_view))
# keep checking with future versions.
if isinstance(obj, pd.DataFrame):
sub("x", "z", obj)
sub("y", "x", obj)
sub("z", "y", obj)
elif isinstance(obj, labels_view):
obj.x, obj.y = obj.y, obj.x
elif isinstance(obj, panel_view):
obj.x, obj.y = obj.y, obj.x
return obj