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

Hypothesis tests for roundtrip to & from pandas #3285

Merged
merged 17 commits into from
Oct 30, 2019

Conversation

takluyver
Copy link
Member

Part of #1846: test roundtripping between xarray DataArray & Dataset and pandas Series & DataFrame.

I haven't particularly tried to hunt down corner cases (e.g. dataframes with 0 columns), in favour of adding tests that currently pass. But these tests probably form a useful platform if you do want to ensure corner cases like that behave nicely - just modify the limits and see what fails.

@max-sixty
Copy link
Collaborator

This looks great! I'll let someone who knows hypothesis better do a full review. Thanks for submitting @takluyver !

Copy link
Contributor

@Zac-HD Zac-HD left a comment

Choose a reason for hiding this comment

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

This looks good to me! Some comments below with config/performance/test tips, but IMO it could easily be merged as-is too 😄

from hypothesis import settings

# Run for a while - arrays are a bigger search space than usual
settings.register_profile("ci", deadline=None)

This comment was marked as resolved.

df.columns.name = "cols"
arr = xr.DataArray(df)
roundtripped = arr.to_pandas()
pd.testing.assert_frame_equal(df, roundtripped)

This comment was marked as resolved.

n_entries = draw(st.integers(min_value=0, max_value=100))
dims = ("rows",)
vars = {}
for _ in range(n_vars):
Copy link
Contributor

Choose a reason for hiding this comment

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

This pattern - draw a number, then draw that many elements - is tempting but tends to be inefficient when Hypothesis tries to minimse any failures.

The alternative, which we recommend, is to generate collections using the st.lists() strategy - that way Hypothesis will be able to operate in terms of elements of the list.

In this case it's probably only worth doing so for either the vars or entries dimension, and keep the other as-is. If you're keen to do both, it's complicated enough that I'd just fall back on the Hypothesis pandas extension and .map(pd.DataFrame.to_xarray) over the result 😅

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'm not sure how to do this, because in both dimension I want to generate multiple things of the same length - same number of names and arrays for the vars dimension, same number of entries in each array for the entries dimension. If I naively generate lists, they'll have different lengths.

Is it better to generate one such things with the lists strategy, and then make the others to match its length, rather than generating a number to use as the length for all of them? Or is there some overall cleverer way that I'm not seeing?

Copy link
Contributor

Choose a reason for hiding this comment

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

You could draw indices before the loop, then draw a list of (name, array) tuples. Or in this case you could use st.dictionaries() to, well, generate a list of key-value tuples internally.

The other nice trick would be to draw your index first, and use it's length - deleting elements from that will be slightly more efficient than shrinking the n_elements parameter.

Putting it all togther, I'd write

idx = draw(pdst.indexes(dtype="u8", min_size=0, max_size=100))
vars_strat = st.dictionaries(
    keys=st.text(),
    values=npst.arrays(dtype=numeric_dtypes, shape=len(idx)).map(partial(xr.Variable, ("rows",))),
    min_size=1,
    max_size=3,
)
return xr.Dataset(draw(vars_strat), coords={"rows": idx})

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, that does look neater!

@takluyver
Copy link
Member Author

As in my other PR, one suggested addition causes a test failure, and I've put that in the last commit.

@pep8speaks
Copy link

pep8speaks commented Oct 12, 2019

Hello @takluyver! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2019-10-30 10:01:16 UTC

@jhamman jhamman mentioned this pull request Oct 12, 2019
9 tasks
@max-sixty
Copy link
Collaborator

This seems so close—could we fix the test (maybe that's just a merging of master?) and merge?

@takluyver
Copy link
Member Author

Merged master, crossing fingers that fixes it.

@takluyver
Copy link
Member Author

Nope. I don't understand the error, though it looks like astropy has had something similar: astropy/astropy#6424

Also black is now failing on a number of files not affected here.

Copy link
Contributor

@dcherian dcherian left a comment

Choose a reason for hiding this comment

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

I think the failures are because hypothesis isn't being installed on all CI environments?

properties/conftest.py Outdated Show resolved Hide resolved
@@ -10,15 +10,10 @@

import hypothesis.extra.numpy as npst
Copy link
Contributor

Choose a reason for hiding this comment

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

These may need to be guarded too using pytest.importorskip perhaps? @max-sixty what do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Aha, I was being distracted by the other errors around the real one. Let's see if the latest commit helps.

@takluyver
Copy link
Member Author

OK, looks like the test failure now is real. Let me know if you want me to comment out the relevant line so the tests pass.

@max-sixty
Copy link
Collaborator

You're right @takluyver

It looks like hypothesis tests are running in the normal test suites. Anyone know offhand why that is? e.g. https://dev.azure.com/xarray/xarray/_build/results?buildId=1284

(that doesn't solve the test failure, though)

@max-sixty
Copy link
Collaborator

OK, looks like the test failure now is real. Let me know if you want me to comment out the relevant line so the tests pass.

If we want to merge a subset of the tests then that's fine. Ofc even better if we can use these tests to find & fix the errors

@Zac-HD
Copy link
Contributor

Zac-HD commented Oct 29, 2019

OK, looks like the test failure now is real. Let me know if you want me to comment out the relevant line so the tests pass.

If we want to merge a subset of the tests then that's fine. Ofc even better if we can use these tests to find & fix the errors

In my experience it's better to open an issue, add an xfail decorator to the test, and merge the tests PR. Otherwise the initial PR can take a very long time and no other property-based tests get added.

In this case I'd duplicate the test, so there's one which does not allow empty dataframes and one (xfailing) which does.

It's also likely that the person who found the bug is not the best person to fix it, and requiring that they do so in order to merge a useful test just disincentives testing!

@shoyer
Copy link
Member

shoyer commented Oct 29, 2019

In my experience it's better to open an issue, add an xfail decorator to the test, and merge the tests PR. Otherwise the initial PR can take a very long time and no other property-based tests get added.

+1 let's do that!

@takluyver
Copy link
Member Author

OK, I've xfailed it.

@dcherian
Copy link
Contributor

Opened #3468 . Thanks @takluyver

@max-sixty
Copy link
Collaborator

Thanks @takluyver. And @Zac-HD for the feedback; v much agree with your approach

dcherian added a commit to dcherian/xarray that referenced this pull request Nov 4, 2019
* upstream/master:
  __dask_tokenize__ (pydata#3446)
  Type check sentinel values (pydata#3472)
  Fix typo in docstring (pydata#3474)
  fix test suite warnings re `drop` (pydata#3460)
  Fix integrate docs (pydata#3469)
  Fix leap year condition in monthly means example (pydata#3464)
  Hypothesis tests for roundtrip to & from pandas (pydata#3285)
  unpin cftime (pydata#3463)
  Cleanup whatsnew (pydata#3462)
  enable xr.ALL_DIMS in xr.dot (pydata#3424)
  Merge stable into master (pydata#3457)
  upgrade black verison to 19.10b0 (pydata#3456)
  Remove outdated code related to compatibility with netcdftime (pydata#3450)
  Remove deprecated behavior from dataset.drop docstring (pydata#3451)
  jupyterlab dark theme (pydata#3443)
  Drop groups associated with nans in group variable (pydata#3406)
  Allow ellipsis (...) in transpose (pydata#3421)
  Another groupby.reduce bugfix. (pydata#3403)
  add icomoon license (pydata#3448)
dcherian added a commit to dcherian/xarray that referenced this pull request Nov 8, 2019
* upstream/master: (27 commits)
  drop_vars; deprecate drop for variables (pydata#3475)
  uamiv test using only raw uamiv variables (pydata#3485)
  Optimize dask array equality checks. (pydata#3453)
  Propagate indexes in DataArray binary operations. (pydata#3481)
  python 3.8 tests (pydata#3477)
  __dask_tokenize__ (pydata#3446)
  Type check sentinel values (pydata#3472)
  Fix typo in docstring (pydata#3474)
  fix test suite warnings re `drop` (pydata#3460)
  Fix integrate docs (pydata#3469)
  Fix leap year condition in monthly means example (pydata#3464)
  Hypothesis tests for roundtrip to & from pandas (pydata#3285)
  unpin cftime (pydata#3463)
  Cleanup whatsnew (pydata#3462)
  enable xr.ALL_DIMS in xr.dot (pydata#3424)
  Merge stable into master (pydata#3457)
  upgrade black verison to 19.10b0 (pydata#3456)
  Remove outdated code related to compatibility with netcdftime (pydata#3450)
  Remove deprecated behavior from dataset.drop docstring (pydata#3451)
  jupyterlab dark theme (pydata#3443)
  ...
@takluyver takluyver deleted the hypothesis-pandas-roundtrip branch January 10, 2020 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants