COMPAT: Objects construction compat with xarray.Dataset 
State: closed

- [x] closes #12353
- [x] tests added 
- [ ] tests passed
- [x] passes `git diff upstream/master | flake8 --diff`
- [ ] whatsnew entry

I'm changed the dict / mapping issue, but I can't get this part working (so the tests fail at the moment):

> But pd.Series(dict(xr.Dataset({'a': 2, 'b': 3}))) doesn't work either, because the values in the dict are 0-th dimension arrays, and Series doesn't unpack them (list(dict(xr.Dataset({'a': 2, 'b': 3})).values())[0] for the full code) 
> https://github.com/pydata/pandas/issues/12353#issuecomment-184968747

Is that a reasonable goal? Where would be a good place to do the conversion?


Labels:
name: Reshaping
description: Concat, Merge/Join, Stack/Unstack, Explode
name: Compat
description: pandas objects compatability with Numpy or Python functions

Comments:
@MaximilianR since you are fixing this, thanks!

can you incoporate anything from my original PR that is needed: https://github.com/pydata/pandas/pull/12356

@jreback Ready to go, less a what's new note and removing a commented out test (this is why the build fails).

Apologies for mixing formatting & functional improvements.

Needs a look through from you, in particular the `to_dataframe` check. 

@MaximilianR if you'd like to rebase/update

Rebased. 
@jreback, awaiting your review

you have some setting on your editor which just messes with existing (correct) linting / formatting. Pls turn that off. Makes it much harder to see what is changing.

Overall I think this approach is nice. `.to_dataframe()` is a good approach / very duck-like.

I've been remiss about the final fixes here. Will need a couple of weeks on other commitments but I will get to this

@MaximilianR ?

Apologies! I will do soon. Please don't close.

@MaximilianR want to rebase?

I would be onboard with allowing a special method ``__dataframe__`` which is pretty clear IMHO.
> I would be onboard with allowing a special method __dataframe__ which is pretty clear IMHO.

At this point there are a number of alternative "dataframe" objects (e.g., dask, spark), many of which probably want to be coercible to pandas, so I think the special method should have `pandas` in the name to clarify. Hence my suggestion for `_to_pandas_dataframe_`.
status?
can you rebase / update
Yes, thanks for your patience. 

What do we want to name the method? `__dataframe__`? `_to_dataframe`?
``__dataframe__``. I don't think it matters that others have dataframes. pandas is the standard in python, just as numpy is for arrays.
I feel pretty strongly that the name should *not* just be `__dataframe__` and we should have `pandas` in it somewhere.

If we were starting over with NumPy, the name probably wouldn't be `__array__`, either.
I don't remember If I suggested the special method, but what is wrong with ``.to_dataframe()``? (or ``.to_pandas()``?
> I don't remember If I suggested the special method, but what is wrong with .to_dataframe()? (or .to_pandas()?

The main reason is that it's totally conceivable that some application might use these for something else, e.g., `to_dataframe()` might make a spark dataframe instead. In fact, xarray sometimes uses `to_pandas()` to create a `pandas.Series` (if the array is 1D). The advantage of looking for a special method with a name like `_to_pandas_dataframe_` is that there is almost no chance that it will be used incorrectly.
@shoyer 

Is this supposed to work?

```
In [30]: x = DataFrame({'A': [1, 2, 3], 'B': [3., 4., 5.]}).to_xarray()

In [31]: x
Out[31]: 
<xarray.Dataset>
Dimensions:  (index: 3)
Coordinates:
  * index    (index) int64 0 1 2
Data variables:
    A        (index) int64 1 2 3
    B        (index) float64 3.0 4.0 5.0

In [32]: np.array(x)
Out[32]: 
array(['index', 'A', 'B'], 
      dtype='<U5')

```
@jreback `xarray.Dataset` is not meant to be convertable to a NumPy array, so it doesn't define `__array__`. But it does subclass `collections.Mapping`, so NumPy apparently manages to convert it by iterating over the keys, like this class:
```python
class WrapMapping(collections.Mapping):
  def __init__(self, mapping):
    self._map = mapping
  def __getitem__(self, key):
    return self._map[key]
  def __iter__(self):
    return iter(self._map)
  def __len__(self):
    return len(self._map)

>>> np.array(WrapMapping({'a': 1, 'b': 2}))
array(['b', 'a'], 
      dtype='|S1')
```

This is totally useless though, so I'll make a note to implement a `__array__` for `Dataset` that just raises `TypeError` with a helpful error message.
@shoyer gotcha, ok, then I guess ``__pandas_dataframe__`` is prob reasonable for external converters.
@MaximilianR rebase?
can you rebase and update?
closing as stale