Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Errors with tz_aware datetime #687

Closed
david-waterworth opened this issue May 18, 2023 · 2 comments
Closed

Errors with tz_aware datetime #687

david-waterworth opened this issue May 18, 2023 · 2 comments

Comments

@david-waterworth
Copy link

david-waterworth commented May 18, 2023

I have data with a datetime64[ns, Australia/Sydney] column which throws an error when I try and plot. A mre is

from plotnine.data import economics

# this works
(ggplot(economics)
 + geom_point(aes('date', 'psavert'))
 + labs(y='personal saving rate')
)

# change the datatype of date from datetime64[ns] (tz_niave] to datetime64[ns, Australia/Sydney]
economics['date'] = economics['date'].dt.tz_localize("Australia/Sydney")

# this throws an exception
(ggplot(economics)
 + geom_point(aes('date', 'psavert'))
 + labs(y='personal saving rate')
)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File [.venv/lib/python3.10/site-packages/IPython/core/formatters.py:708](.venv/lib/python3.10/site-packages/IPython/core/formatters.py:708), in PlainTextFormatter.__call__(self, obj)
    701 stream = StringIO()
    702 printer = pretty.RepresentationPrinter(stream, self.verbose,
    703     self.max_width, self.newline,
    704     max_seq_length=self.max_seq_length,
    705     singleton_pprinters=self.singleton_printers,
    706     type_pprinters=self.type_printers,
    707     deferred_pprinters=self.deferred_printers)
--> 708 printer.pretty(obj)
    709 printer.flush()
    710 return stream.getvalue()

File [.venv/lib/python3.10/site-packages/IPython/lib/pretty.py:410](.venv/lib/python3.10/site-packages/IPython/lib/pretty.py:410), in RepresentationPrinter.pretty(self, obj)
    407                         return meth(obj, self, cycle)
    408                 if cls is not object \
    409                         and callable(cls.__dict__.get('__repr__')):
--> 410                     return _repr_pprint(obj, self, cycle)
    412     return _default_pprint(obj, self, cycle)
    413 finally:

File [.venv/lib/python3.10/site-packages/IPython/lib/pretty.py:778](.venv/lib/python3.10/site-packages/IPython/lib/pretty.py:778), in _repr_pprint(obj, p, cycle)
    776 """A pprint that just redirects to the normal repr function."""
    777 # Find newlines and replace them with p.break_()
--> 778 output = repr(obj)
    779 lines = output.splitlines()
    780 with p.group():

File [.venv/lib/python3.10/site-packages/plotnine/ggplot.py:114](.venv/lib/python3.10/site-packages/plotnine/ggplot.py:114), in ggplot.__repr__(self)
    110 def __repr__(self) -> str:
    111     """
    112     Print[/show](https://file+.vscode-resource.vscode-cdn.net/show) the plot
    113     """
--> 114     figure = self.draw(show=True)
    116     dpi = figure.get_dpi()
    117     W = int(figure.get_figwidth() * dpi)

File [.venv/lib/python3.10/site-packages/plotnine/ggplot.py:224](.venv/lib/python3.10/site-packages/plotnine/ggplot.py:224), in ggplot.draw(self, show)
    222 self = deepcopy(self)
    223 with plot_context(self, show=show):
--> 224     self._build()
    226     # setup
    227     figure, axs = self._create_figure()

File [.venv/lib/python3.10/site-packages/plotnine/ggplot.py:352](.venv/lib/python3.10/site-packages/plotnine/ggplot.py:352), in ggplot._build(self)
    349     layers.map(npscales)
    351 # Train coordinate system
--> 352 layout.setup_panel_params(self.coordinates)
    354 # fill in the defaults
    355 layers.use_defaults()

File [.venv/lib/python3.10/site-packages/plotnine/facets/layout.py:199](.venv/lib/python3.10/site-packages/plotnine/facets/layout.py:199), in Layout.setup_panel_params(self, coord)
    197 for i, j in self.layout[cols].itertuples(index=False):
    198     i, j = i - 1, j - 1
--> 199     params = coord.setup_panel_params(
    200         self.panel_scales_x[i], self.panel_scales_y[j]
    201     )
    202     self.panel_params.append(params)

File [.venv/lib/python3.10/site-packages/plotnine/coords/coord_cartesian.py:82](.venv/lib/python3.10/site-packages/plotnine/coords/coord_cartesian.py:82), in coord_cartesian.setup_panel_params(self, scale_x, scale_y)
     78     sv = scale.view(limits=coord_limits, range=ranges.range)
     79     return sv
     81 out = panel_view(
---> 82     x=get_scale_view(scale_x, self.limits.x),
     83     y=get_scale_view(scale_y, self.limits.y),
     84 )
     85 return out

File [.venv/lib/python3.10/site-packages/plotnine/coords/coord_cartesian.py:78](.venv/lib/python3.10/site-packages/plotnine/coords/coord_cartesian.py:78), in coord_cartesian.setup_panel_params..get_scale_view(scale, coord_limits)
     74 expansion = scale.default_expansion(expand=self.expand)
     75 ranges = scale.expand_limits(
     76     scale.limits, expansion, coord_limits, identity_trans
     77 )
---> 78 sv = scale.view(limits=coord_limits, range=ranges.range)
     79 return sv

File [.venv/lib/python3.10/site-packages/plotnine/scales/scale.py:884](.venv/lib/python3.10/site-packages/plotnine/scales/scale.py:884), in scale_continuous.view(self, limits, range)
    881     range = self.dimension(limits=limits)
    883 breaks = self.get_bounded_breaks(range)
--> 884 labels = self.get_labels(breaks)
    886 ubreaks = self.get_breaks(range)
    887 minor_breaks = self.get_minor_breaks(ubreaks, range)

File [.venv/lib/python3.10/site-packages/plotnine/scales/scale.py:1041](.venv/lib/python3.10/site-packages/plotnine/scales/scale.py:1041), in scale_continuous.get_labels(self, breaks)
   1038 breaks = self.inverse(breaks)
   1040 if self.labels is True:
-> 1041     labels: Sequence[str] = self.trans.format(breaks)
   1042 elif self.labels in (False, None):
   1043     labels = []

File [.venv/lib/python3.10/site-packages/mizani/formatters.py:613](.venv/lib/python3.10/site-packages/mizani/formatters.py:613), in date_format.__call__(self, x)
    606     if not all(value.tzinfo == tz for value in x):
    607         msg = (
    608             "Dates have different time zones. "
    609             "Choosen `{}` the time zone of the first date. "
    610             "To use a different time zone, create a "
    611             "formatter and pass the time zone."
    612         )
--> 613         warn(msg.format(tz.key))
    615 # The formatter is tied to axes and takes
    616 # breaks in ordinal format.
    617 x = [date2num(val) for val in x]

AttributeError: 'Australia/Sydney' object has no attribute 'key'
@has2k1
Copy link
Owner

has2k1 commented May 18, 2023

The bug is in mizani.

has2k1 added a commit to has2k1/mizani that referenced this issue May 18, 2023
This works with datetime.tzinfo subclasses from zoneinfo and pytz.

closes has2k1/plotnine#687
@has2k1
Copy link
Owner

has2k1 commented May 19, 2023

The fix is out, you can get with pip install --upgrade mizani or conda upgrade mizani.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants