{"action":"created","issue":{"url":"https://api.github.com/repos/theislab/anndata/issues/60","repository_url":"https://api.github.com/repos/theislab/anndata","labels_url":"https://api.github.com/repos/theislab/anndata/issues/60/labels{/name}","comments_url":"https://api.github.com/repos/theislab/anndata/issues/60/comments","events_url":"https://api.github.com/repos/theislab/anndata/issues/60/events","html_url":"https://github.com/theislab/anndata/issues/60","id":359028621,"node_id":"MDU6SXNzdWUzNTkwMjg2MjE=","number":60,"title":"Error slicing when there is only one observation","user":{"login":"bretttully","id":5830269,"node_id":"MDQ6VXNlcjU4MzAyNjk=","avatar_url":"https://avatars1.githubusercontent.com/u/5830269?v=4","gravatar_id":"","url":"https://api.github.com/users/bretttully","html_url":"https://github.com/bretttully","followers_url":"https://api.github.com/users/bretttully/followers","following_url":"https://api.github.com/users/bretttully/following{/other_user}","gists_url":"https://api.github.com/users/bretttully/gists{/gist_id}","starred_url":"https://api.github.com/users/bretttully/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bretttully/subscriptions","organizations_url":"https://api.github.com/users/bretttully/orgs","repos_url":"https://api.github.com/users/bretttully/repos","events_url":"https://api.github.com/users/bretttully/events{/privacy}","received_events_url":"https://api.github.com/users/bretttully/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2018-09-11T12:40:00Z","updated_at":"2018-09-19T10:35:58Z","closed_at":null,"author_association":"NONE","body":"This may be intentional, but there seems to be an issue when the raw data only has one row. We have come across this in our unit tests when creating a small example data set with only one observation.\r\n\r\n```python\r\nIn [1]: import anndata\r\n\r\nIn [2]: anndata.__version__\r\nOut[2]: '0.6.10'\r\n\r\nIn [3]: import pandas as pd\r\n\r\nIn [4]: d = [\r\n   ...:     (1, 'A', 'a', 'Z', 'z'),\r\n   ...:     (2, 'A', 'b', 'Z', 'z'),\r\n   ...:     (3, 'B', 'c', 'Z', 'z'),\r\n   ...:     (4, 'B', 'd', 'Z', 'z'),\r\n   ...: ]\r\n\r\nIn [5]: df = pd.DataFrame(d, columns='c0 c1 c2 c3 c4'.split())\r\n   ...: df\r\nOut[5]:\r\n   c0 c1 c2 c3 c4\r\n0   1  A  a  Z  z\r\n1   2  A  b  Z  z\r\n2   3  B  c  Z  z\r\n3   4  B  d  Z  z\r\n\r\nIn [6]: df = df.set_index('c1 c2 c3 c4'.split())['c0'].unstack(level=[2, 3]).T\r\n   ...: df\r\nOut[6]:\r\nc1     A     B\r\nc2     a  b  c  d\r\nc3 c4\r\nZ  z   1  2  3  4\r\n\r\nIn [7]: def convert_idx(x): return x.to_frame().reset_index(drop=True)\r\n\r\nIn [8]: obs = convert_idx(df.index)\r\n\r\nIn [9]: var = convert_idx(df.columns)\r\n\r\nIn [10]: a = anndata.AnnData(X=df.values, obs=obs, var=var)\r\n\r\nIn [11]: a\r\nOut[11]:\r\nAnnData object with n_obs × n_vars = 1 × 4\r\n    obs: 'c3', 'c4'\r\n    var: 'c1', 'c2'\r\n\r\nIn [12]: a.obs\r\nOut[12]:\r\n  c3 c4\r\n0  Z  z\r\n\r\nIn [13]: a.var\r\nOut[13]:\r\n  c1 c2\r\n0  A  a\r\n1  A  b\r\n2  B  c\r\n3  B  d\r\n\r\nIn [14]: assert a.shape == a.X.shape, '{} != {}'.format(a.shape, a.X.shape)\r\n---------------------------------------------------------------------------\r\nAssertionError                            Traceback (most recent call last)\r\n<ipython-input-14-7f38676dce05> in <module>()\r\n----> 1 assert a.shape == a.X.shape, '{} != {}'.format(a.shape, a.X.shape)\r\n\r\nAssertionError: (1, 4) != (4,)\r\n\r\nIn [15]: a[0, 0]\r\n---------------------------------------------------------------------------\r\nIndexError                                Traceback (most recent call last)\r\n<ipython-input-15-0d768f50cb80> in <module>()\r\n----> 1 a[0, 0]\r\n\r\n~/anaconda3/envs/dev-procanswon-py/lib/python3.6/site-packages/anndata/base.py in __getitem__(self, index)\r\n   1292     def __getitem__(self, index):\r\n   1293         \"\"\"Returns a sliced view of the object.\"\"\"\r\n-> 1294         return self._getitem_view(index)\r\n   1295\r\n   1296     def _getitem_view(self, index):\r\n\r\n~/anaconda3/envs/dev-procanswon-py/lib/python3.6/site-packages/anndata/base.py in _getitem_view(self, index)\r\n   1296     def _getitem_view(self, index):\r\n   1297         oidx, vidx = self._normalize_indices(index)\r\n-> 1298         return AnnData(self, oidx=oidx, vidx=vidx, asview=True)\r\n   1299\r\n   1300     # this is used in the setter for uns, if a view\r\n\r\n~/anaconda3/envs/dev-procanswon-py/lib/python3.6/site-packages/anndata/base.py in __init__(self, X, obs, var, uns, obsm, varm, layers, raw, dtype, shape, filename, filemode, asview, oidx, vidx)\r\n    674             if not isinstance(X, AnnData):\r\n    675                 raise ValueError('`X` has to be an AnnData object.')\r\n--> 676             self._init_as_view(X, oidx, vidx)\r\n    677         else:\r\n    678             self._init_as_actual(\r\n\r\n~/anaconda3/envs/dev-procanswon-py/lib/python3.6/site-packages/anndata/base.py in _init_as_view(self, adata_ref, oidx, vidx)\r\n    735         # set data\r\n    736         if self.isbacked: self._X = None\r\n--> 737         else: self._init_X_as_view()\r\n    738\r\n    739         self._layers = AnnDataLayers(self, adata_ref=adata_ref, oidx=oidx, vidx=vidx)\r\n\r\n~/anaconda3/envs/dev-procanswon-py/lib/python3.6/site-packages/anndata/base.py in _init_X_as_view(self)\r\n    750             self._X = None\r\n    751             return\r\n--> 752         X = self._adata_ref.X[self._oidx, self._vidx]\r\n    753         if len(X.shape) == 2:\r\n    754             n_obs, n_vars = X.shape\r\n\r\nIndexError: too many indices for array\r\n```"},"comment":{"url":"https://api.github.com/repos/theislab/anndata/issues/comments/422749492","html_url":"https://github.com/theislab/anndata/issues/60#issuecomment-422749492","issue_url":"https://api.github.com/repos/theislab/anndata/issues/60","id":422749492,"node_id":"MDEyOklzc3VlQ29tbWVudDQyMjc0OTQ5Mg==","user":{"login":"falexwolf","id":16916678,"node_id":"MDQ6VXNlcjE2OTE2Njc4","avatar_url":"https://avatars1.githubusercontent.com/u/16916678?v=4","gravatar_id":"","url":"https://api.github.com/users/falexwolf","html_url":"https://github.com/falexwolf","followers_url":"https://api.github.com/users/falexwolf/followers","following_url":"https://api.github.com/users/falexwolf/following{/other_user}","gists_url":"https://api.github.com/users/falexwolf/gists{/gist_id}","starred_url":"https://api.github.com/users/falexwolf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/falexwolf/subscriptions","organizations_url":"https://api.github.com/users/falexwolf/orgs","repos_url":"https://api.github.com/users/falexwolf/repos","events_url":"https://api.github.com/users/falexwolf/events{/privacy}","received_events_url":"https://api.github.com/users/falexwolf/received_events","type":"User","site_admin":false},"created_at":"2018-09-19T10:35:58Z","updated_at":"2018-09-19T10:35:58Z","author_association":"MEMBER","body":"> This would be useful in the constructor, yes -- would you try and persist that when creating a view/copy of the object? I'm ambivalent as to how that should work.\r\n\r\nOf course, this would persist throughout copies and views. Wouldn't be a problem.\r\n\r\nJust yesterday, another question came up regarding efficient extraction of a slice of `.X` from an AnnData (https://github.com/theislab/scanpy/pull/244#issuecomment-422400480). As it's likely needed that another accessor is written for this, and as this could serve as a convenience accessor that provides (n x 1) matrices as vectors to users, I can now think of an AnnData whose data matrix is always 2d. (I previously admitted that \"another access operation\" that would provide 1d vectors would have been the better design choice and @flying-sheep always wanted to keep things 2d: https://github.com/theislab/anndata/pull/55)\r\n\r\n- We need to think about how to make this an easy transition for users, many of them have the call `adata[:, 'gene_name'].X` in their code and expect it to return a vector. While enforcing `._X` to be always 2d could be done in a backwards compatible way by calling `.flatten` in the property `.X` if `._X` is (n x 1), this wouldn't make you happy, right? Your test above would still break.\r\n- We need an elegant name for the convenience access: I guess I'd call it `.slice` as `.sliceX` is ugly. Calling `.slice` wouldn't slice the whole AnnData but only return a slice of the data matrix potentially returning something flattened.\r\n\r\n@flying-sheep: You don't need to go through the whole issue, just consider the two bullets above. What do you think? I guess you would be happier with this\r\n\r\n\r\n"}}
{"actor":{"display_login":"falexwolf"}}