Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ENH: support np.datenum64 in dates.py #9779

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

Merged
merged 1 commit into from
Nov 15, 2017

Conversation

jklymak
Copy link
Member

@jklymak jklymak commented Nov 14, 2017

PR Summary

This allows numpy.datetime64 dates. New and improved!

time = [base - datetime.timedelta(days=x) + datetime.timedelta(seconds=0.900001) for x in range(0, 3)]

timenp = np.array(time, dtype='datetime64[us]')

fig, ax = plt.subplots(tight_layout=True)
ax.plot( time, data)
ax.plot( timenp, data+.1, )

works fine.

PR Checklist

  • Has Pytest style unit tests
  • Code is PEP 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@dstansby dstansby added this to the v2.2 milestone Nov 14, 2017
@@ -211,36 +211,58 @@ def _get_rc_timezone():
WEEKDAYS = (MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY)


def _to_ordinalf(dt):
def _to_ordinalf(dts):
Copy link
Member

@dstansby dstansby Nov 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's probably worth writing a new function called something like _dtime64_to_ordinalf(dts) with the new code to handle np.datetime64s. (for clarity)

@dstansby
Copy link
Member

xref #9610

@efiring
Copy link
Member

efiring commented Nov 14, 2017

The normal use case would be with an ndarray of dtype np.datetime64. The conversion of this to matplotlib float datenums should be direct and vectorized--no loop--otherwise the performance will be terrible.

@@ -1183,9 +1209,8 @@ def get_locator(self, dmin, dmax):

locator.set_axis(self.axis)

if self.axis is not None:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooops, I guess I missed a rebase here. Will fix after

@jklymak jklymak force-pushed the add-datenum64 branch 4 times, most recently from ec3ec37 to a32aa1b Compare November 14, 2017 18:48
zerod = False
if isinstance(d, np.datetime64):
zerod = True
d = np.atleast_1d(d)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It runs for me without converting a single item into array and back. This is needed for some older numpy (mine is 1.13.3)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I didn't even try! You're right..

d = np.atleast_1d(d)
extra = d - d.astype('datetime64[s]')
extra = extra.astype('timedelta64[ns]')
t0 = np.datetime64('0001-01-01T00:00:00').astype('datetime64[s]')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t0 = np.datetime64('0001-01-01T00:00:00', 's')

@@ -22,6 +23,52 @@
import matplotlib.dates as mdates


def test_date_numpyx():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason this isn't done with base/time/timenp being pytest fixtures and the test parameterized or split into two?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I can understand this, and I have no idea what a pytest fixture is. Is there an advantage to doing something more obscure than a simple assert?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only cause you're repeating yourself a lot so it's hard to tell what the specific tests are. Factoring out common features into a fixture means you can make two tests that are uniquely named for the things they're testing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into it. OTOH, I find some of the tests aren't very easy to follow. Sometime verbosity is a good thing!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, happy to take suggestions, but I find the uses of fixtures in the existing tests makes for pretty obfuscated code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shrugs can agree on that somewhat, either way it's not something I'd hold the PR up on.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I didn't mean to say I wasn't willing to learn, just that I don't get it... More than happy if you wanted to push a change or give me some pseudo code to get it to work... Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for missing your reply (the embedded ones seem to not pop up as notifications), and will totally try to remember your suggestion for the future. I should have been way clearer on what I wanted and given you an example. :/

assert np.array_equal(h.get_ydata(orig=False), hnp.get_ydata(orig=False))


def test_date_date2num_numpy():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, could this be parameterized with ids?

Copy link
Member

@dstansby dstansby Nov 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sympathise with @jklymak re. pytest, (I still have no idea what a fixture is) but find paramaterising fairly easy to understand (https://docs.pytest.org/en/latest/parametrize.html)

Something like this should work:

@pytest.mark.parametrize('t0', [datetime.datetime(2017, 1, 1, 0, 1, 1),

                                [datetime.datetime(2017, 1, 1, 0, 1, 1),
                                 datetime.datetime(2017, 1, 1, 1, 1, 1)],

                                [[datetime.datetime(2017, 1, 1, 0, 1, 1),
                                  datetime.datetime(2017, 1, 1, 1, 1, 1)],
                                 [datetime.datetime(2017, 1, 1, 2, 1, 1),
                                  datetime.datetime(2017, 1, 1, 3, 1, 1)]]])
@pytest.mark.parameterize('dtype', ['datetime64[s]',
                                    'datetime64[us]',
                                    'datetime64[ms]'])
def test_date_numpyx(t0, dytpe):
    time = mdates.date2num(t0)
    tnp = np.array(t0, dtype=dtype)
    nptime = mdates.date2num(tnp)
    assert time == nptime

This will run through every possible combination of t0 and dtype, and avoids copy/pasting the actual testing code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I agree that parametrize works well here (despite pytests odd way of spelling it) Thanks for the example!

Copy link
Member

@dstansby dstansby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Looks good to me, thanks a lot for squashing this long running bug! I'm happy to tidy up the tests if you want @jklymak?

@Kojoley Kojoley merged commit 3ccaf2d into matplotlib:master Nov 15, 2017
@tacaswell
Copy link
Member

That was easier than I expected...

@tacaswell
Copy link
Member

Could someone open up a follow-on PR to add a whats_new about this?

@jklymak
Copy link
Member Author

jklymak commented Nov 15, 2017

Oops sorry I’ll do so tonight and prob add an example as well.

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

Successfully merging this pull request may close these issues.

7 participants