-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Hypothesis tests for roundtrip to & from pandas #3285
Conversation
This looks great! I'll let someone who knows hypothesis better do a full review. Thanks for submitting @takluyver ! |
There was a problem hiding this 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 😄
properties/conftest.py
Outdated
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.
This comment was marked as resolved.
Sorry, something went wrong.
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.
This comment was marked as resolved.
Sorry, something went wrong.
properties/test_pandas_roundtrip.py
Outdated
n_entries = draw(st.integers(min_value=0, max_value=100)) | ||
dims = ("rows",) | ||
vars = {} | ||
for _ in range(n_vars): |
There was a problem hiding this comment.
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 😅
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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})
There was a problem hiding this comment.
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!
As in my other PR, one suggested addition causes a test failure, and I've put that in the last commit. |
Following suggestions from @Zac-HD
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 |
This seems so close—could we fix the test (maybe that's just a merging of master?) and merge? |
Merged master, crossing fingers that fixes it. |
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. |
There was a problem hiding this 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?
@@ -10,15 +10,10 @@ | |||
|
|||
import hypothesis.extra.numpy as npst |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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.
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. |
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) |
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! |
+1 let's do that! |
OK, I've xfailed it. |
Opened #3468 . Thanks @takluyver |
Thanks @takluyver. And @Zac-HD for the feedback; v much agree with your approach |
* 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)
* 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) ...
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.