{"action":"created","comment":{"url":"https://api.github.com/repos/xray/xray/pulls/comments/46492355","id":46492355,"diff_hunk":"@@ -0,0 +1,238 @@\n+import numpy as np\n+import bottleneck as bn\n+\n+from .pycompat import OrderedDict, zip\n+\n+from .common import ImplementsArrayReduce\n+\n+\n+class Rolling(object):\n+    \"\"\"A object that implements the moving window pattern.\n+\n+    See Also\n+    --------\n+    Dataset.groupby\n+    DataArray.groupby\n+    Dataset.rolling\n+    DataArray.rolling\n+    \"\"\"\n+\n+    _attributes = ['window', 'min_periods', 'center', 'dim']\n+\n+    def __init__(self, obj, min_periods=None, center=False, **kwarg):\n+        \"\"\"\n+        Moving window object.\n+\n+        Parameters\n+        ----------\n+        obj : Dataset or DataArray\n+            Object to window.\n+        min_periods : int, default None\n+            Minimum number of observations in window required to have a value\n+            (otherwise result is NA). The default, None, is equivalent to\n+            setting min_periods equal to the size of the window.\n+        center : boolean, default False\n+            Set the labels at the center of the window.\n+        kwarg : dim=window\n+            dim : str\n+                Name of the dimension to create the rolling iterator\n+                along (e.g., `time`).\n+            window : int\n+                Size of the moving window.\n+\n+        Returns\n+        -------\n+        rolling : type of input argument\n+        \"\"\"\n+\n+        if len(kwarg) != 1:\n+            raise ValueError('only one dim/window can be provided')\n+\n+        dim, window = next(iter(kwarg.items()))\n+\n+        if window <= 0:\n+            raise ValueError('window must be > 0')\n+\n+        self.obj = obj\n+\n+        # attributes\n+        self.window = window\n+        self.min_periods = min_periods\n+        self.center = center\n+        self.dim = dim\n+\n+        self._axis_num = self.obj.get_axis_num(self.dim)\n+\n+        self._windows = None\n+        self._valid_windows = None\n+        self.window_indices = None\n+        self.window_labels = None\n+\n+        self._setup_windows(min_periods=min_periods, center=center)\n+\n+    def __unicode__(self):\n+        \"\"\" provide a nice str repr of our rolling object \"\"\"\n+\n+        attrs = [\"{k}->{v}\".format(k=k, v=getattr(self, k))\n+                 for k in self._attributes if getattr(self, k, None) is not None]\n+        return \"{klass} [{attrs}]\".format(klass=self.__class__.__name__,\n+                                          attrs=','.join(attrs))\n+\n+    @property\n+    def windows(self):\n+        if self._windows is None:\n+            self._windows = OrderedDict(zip(self.window_labels,\n+                                            self.window_indices))\n+        return self._windows\n+\n+    def __len__(self):\n+        return len(self.obj[self.dim])\n+\n+    def __iter__(self):\n+        for (label, indices, valid) in zip(self.window_labels,\n+                                           self.window_indices,\n+                                           self._valid_windows):\n+            if valid:\n+                yield (label, self.obj.isel(**{self.dim: indices}))\n+            else:\n+                # return nans for this window\n+                temp = self.obj.isel(**{self.dim: indices}).copy()\n+                temp.values[:] = np.nan\n+                yield (label, temp)\n+\n+    def _setup_windows(self, min_periods=None, center=False):\n+        \"\"\"\n+        Find the indicies and labels for each window\n+        \"\"\"\n+        from .dataarray import DataArray\n+\n+        window = int(self.window)\n+        if min_periods is None:\n+            min_periods = window\n+\n+        dim_size = self.obj[self.dim].size\n+\n+        stops = np.arange(dim_size) + 1\n+        starts = np.maximum(stops - window, 0)\n+\n+        if min_periods > 1:\n+            self._valid_windows = stops - starts >= min_periods\n+        else:\n+            # No invalid windows\n+            self._valid_windows = np.ones(dim_size, dtype=bool)\n+\n+        self.window_indices = [slice(start, stop)\n+                               for start, stop in zip(starts, stops)]\n+\n+        # Get window labels\n+        if not center:\n+            # get labels on the left (these are the same as the current coords)\n+            self.window_labels = self.obj[self.dim]\n+        else:\n+            coord = self.obj[self.dim].copy()\n+            orig_dtype = coord.dtype\n+\n+            # mean does not work on datetime64 objects\n+            if np.issubdtype(coord.dtype, np.datetime64):\n+                coord = coord.astype('int64')\n+\n+            labels = [coord[s].mean().item() for s in self.window_indices]\n+\n+            self.window_labels = DataArray(labels,\n+                                           dims=coord.dims,\n+                                           name=coord.name,\n+                                           attrs=coord.attrs).astype(orig_dtype)\n+\n+    def sum(self):\n+        \"\"\"thin wrapper around bottleneck.move_sum\"\"\"\n+        from .dataarray import DataArray\n+\n+        values = bn.move_sum(self.obj.values, window=self.window,\n+                             min_count=self.min_periods, axis=self._axis_num)\n+        coords = self.obj.coords\n+        coords[self.dim] = self.window_labels\n+        return DataArray(values, coords)\n+\n+    def mean(self):\n+        \"\"\"thin wrapper around bottleneck.move_mean\"\"\"\n+        from .dataarray import DataArray\n+\n+        values = bn.move_mean(self.obj.values, window=self.window,\n+                              min_count=self.min_periods, axis=self._axis_num)\n+        coords = self.obj.coords\n+        coords[self.dim] = self.window_labels\n+        return DataArray(values, coords)\n+\n+    def std(self):\n+        \"\"\"thin wrapper around bottleneck.move_std\"\"\"\n+        from .dataarray import DataArray\n+\n+        values = bn.move_std(self.obj.values, window=self.window,\n+                             min_count=self.min_periods, axis=self._axis_num)\n+        coords = self.obj.coords\n+        coords[self.dim] = self.window_labels\n+        return DataArray(values, coords)\n+\n+    def min(self):\n+        \"\"\"thin wrapper around bottleneck.move_min\"\"\"\n+        from .dataarray import DataArray\n+\n+        values = bn.move_min(self.obj.values, window=self.window,\n+                             min_count=self.min_periods, axis=self._axis_num)\n+        coords = self.obj.coords\n+        coords[self.dim] = self.window_labels\n+        return DataArray(values, coords)\n+\n+    def max(self):\n+        \"\"\"thin wrapper around bottleneck.move_max\"\"\"\n+        from .dataarray import DataArray\n+\n+        values = bn.move_max(self.obj.values, window=self.window,\n+                             min_count=self.min_periods, axis=self._axis_num)\n+        coords = self.obj.coords\n+        coords[self.dim] = self.window_labels\n+        return DataArray(values, coords)\n+\n+    def median(self):\n+        \"\"\"thin wrapper around bottleneck.move_median\"\"\"\n+        from .dataarray import DataArray\n+\n+        if self.min_periods is not None:\n+            # should we raise an error here?","path":"xray/core/rolling.py","position":201,"original_position":201,"commit_id":"1a4adef9c52f79f24fbb3f28306b9f70c5abe280","original_commit_id":"1a4adef9c52f79f24fbb3f28306b9f70c5abe280","user":{"login":"shoyer","id":1217238,"avatar_url":"https://avatars.githubusercontent.com/u/1217238?v=3","gravatar_id":"","url":"https://api.github.com/users/shoyer","html_url":"https://github.com/shoyer","followers_url":"https://api.github.com/users/shoyer/followers","following_url":"https://api.github.com/users/shoyer/following{/other_user}","gists_url":"https://api.github.com/users/shoyer/gists{/gist_id}","starred_url":"https://api.github.com/users/shoyer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shoyer/subscriptions","organizations_url":"https://api.github.com/users/shoyer/orgs","repos_url":"https://api.github.com/users/shoyer/repos","events_url":"https://api.github.com/users/shoyer/events{/privacy}","received_events_url":"https://api.github.com/users/shoyer/received_events","type":"User","site_admin":false},"body":"yes, this is the right call","created_at":"2015-12-02T23:24:07Z","updated_at":"2015-12-02T23:24:07Z","html_url":"https://github.com/xray/xray/pull/668#discussion_r46492355","pull_request_url":"https://api.github.com/repos/xray/xray/pulls/668","_links":{"self":{"href":"https://api.github.com/repos/xray/xray/pulls/comments/46492355"},"html":{"href":"https://github.com/xray/xray/pull/668#discussion_r46492355"},"pull_request":{"href":"https://api.github.com/repos/xray/xray/pulls/668"}}},"pull_request":{"url":"https://api.github.com/repos/xray/xray/pulls/668","id":52455751,"html_url":"https://github.com/xray/xray/pull/668","diff_url":"https://github.com/xray/xray/pull/668.diff","patch_url":"https://github.com/xray/xray/pull/668.patch","issue_url":"https://api.github.com/repos/xray/xray/issues/668","number":668,"state":"open","locked":false,"title":"Feature/rolling","user":{"login":"jhamman","id":2443309,"avatar_url":"https://avatars.githubusercontent.com/u/2443309?v=3","gravatar_id":"","url":"https://api.github.com/users/jhamman","html_url":"https://github.com/jhamman","followers_url":"https://api.github.com/users/jhamman/followers","following_url":"https://api.github.com/users/jhamman/following{/other_user}","gists_url":"https://api.github.com/users/jhamman/gists{/gist_id}","starred_url":"https://api.github.com/users/jhamman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jhamman/subscriptions","organizations_url":"https://api.github.com/users/jhamman/orgs","repos_url":"https://api.github.com/users/jhamman/repos","events_url":"https://api.github.com/users/jhamman/events{/privacy}","received_events_url":"https://api.github.com/users/jhamman/received_events","type":"User","site_admin":false},"body":"This is an initial take at the rolling aggregation object and methods in xray.  This PR implements:\r\n\r\n- A new `Rolling` class available in `DataArray` objects:\r\n    \r\n    ```Python\r\n    rolling_obj = da.rolling(time=7)\r\n   ```\r\n- `bottleneck.move_*` functions are wrapped and are available in the following manor:\r\n\r\n    ```Python\r\n    rolling_obj.mean()\r\n    ```\r\n- generic reduce method\r\n\r\n    ```Python\r\n    from numpy import nanpercentile\r\n    rolling_obj.reduce(nanpercentile, q=5)\r\n    ```\r\n- iterating through the rolling object:\r\n\r\n    ```Python\r\n     for label, da_window in rolling_obj:\r\n         # da_window is a view of da\r\n    ````\r\n\r\nTODO:\r\n\r\n- [ ] Documentation\r\n- [ ] Cleanup `_setup_windows`\r\n- [ ] Inject bottleneck methods in some generic way\r\n- [ ] Possibly create a `Window` object to hold windowed `DataArray`s\r\n\r\ncloses #641 #130\r\nxref pydata/pandas#11603, pydata/pandas#11704\r\ncc @shoyer @bartnijssen","created_at":"2015-12-02T21:20:34Z","updated_at":"2015-12-02T23:24:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c02f854c603977f811096e9e28da737ae9af4211","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/xray/xray/pulls/668/commits","review_comments_url":"https://api.github.com/repos/xray/xray/pulls/668/comments","review_comment_url":"https://api.github.com/repos/xray/xray/pulls/comments{/number}","comments_url":"https://api.github.com/repos/xray/xray/issues/668/comments","statuses_url":"https://api.github.com/repos/xray/xray/statuses/1a4adef9c52f79f24fbb3f28306b9f70c5abe280","head":{"label":"jhamman:feature/Rolling","ref":"feature/Rolling","sha":"1a4adef9c52f79f24fbb3f28306b9f70c5abe280","user":{"login":"jhamman","id":2443309,"avatar_url":"https://avatars.githubusercontent.com/u/2443309?v=3","gravatar_id":"","url":"https://api.github.com/users/jhamman","html_url":"https://github.com/jhamman","followers_url":"https://api.github.com/users/jhamman/followers","following_url":"https://api.github.com/users/jhamman/following{/other_user}","gists_url":"https://api.github.com/users/jhamman/gists{/gist_id}","starred_url":"https://api.github.com/users/jhamman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jhamman/subscriptions","organizations_url":"https://api.github.com/users/jhamman/orgs","repos_url":"https://api.github.com/users/jhamman/repos","events_url":"https://api.github.com/users/jhamman/events{/privacy}","received_events_url":"https://api.github.com/users/jhamman/received_events","type":"User","site_admin":false},"repo":{"id":17182939,"name":"xray","full_name":"jhamman/xray","owner":{"login":"jhamman","id":2443309,"avatar_url":"https://avatars.githubusercontent.com/u/2443309?v=3","gravatar_id":"","url":"https://api.github.com/users/jhamman","html_url":"https://github.com/jhamman","followers_url":"https://api.github.com/users/jhamman/followers","following_url":"https://api.github.com/users/jhamman/following{/other_user}","gists_url":"https://api.github.com/users/jhamman/gists{/gist_id}","starred_url":"https://api.github.com/users/jhamman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jhamman/subscriptions","organizations_url":"https://api.github.com/users/jhamman/orgs","repos_url":"https://api.github.com/users/jhamman/repos","events_url":"https://api.github.com/users/jhamman/events{/privacy}","received_events_url":"https://api.github.com/users/jhamman/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jhamman/xray","description":"Objects for holding self describing scientific data in python.","fork":true,"url":"https://api.github.com/repos/jhamman/xray","forks_url":"https://api.github.com/repos/jhamman/xray/forks","keys_url":"https://api.github.com/repos/jhamman/xray/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jhamman/xray/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jhamman/xray/teams","hooks_url":"https://api.github.com/repos/jhamman/xray/hooks","issue_events_url":"https://api.github.com/repos/jhamman/xray/issues/events{/number}","events_url":"https://api.github.com/repos/jhamman/xray/events","assignees_url":"https://api.github.com/repos/jhamman/xray/assignees{/user}","branches_url":"https://api.github.com/repos/jhamman/xray/branches{/branch}","tags_url":"https://api.github.com/repos/jhamman/xray/tags","blobs_url":"https://api.github.com/repos/jhamman/xray/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jhamman/xray/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jhamman/xray/git/refs{/sha}","trees_url":"https://api.github.com/repos/jhamman/xray/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jhamman/xray/statuses/{sha}","languages_url":"https://api.github.com/repos/jhamman/xray/languages","stargazers_url":"https://api.github.com/repos/jhamman/xray/stargazers","contributors_url":"https://api.github.com/repos/jhamman/xray/contributors","subscribers_url":"https://api.github.com/repos/jhamman/xray/subscribers","subscription_url":"https://api.github.com/repos/jhamman/xray/subscription","commits_url":"https://api.github.com/repos/jhamman/xray/commits{/sha}","git_commits_url":"https://api.github.com/repos/jhamman/xray/git/commits{/sha}","comments_url":"https://api.github.com/repos/jhamman/xray/comments{/number}","issue_comment_url":"https://api.github.com/repos/jhamman/xray/issues/comments{/number}","contents_url":"https://api.github.com/repos/jhamman/xray/contents/{+path}","compare_url":"https://api.github.com/repos/jhamman/xray/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jhamman/xray/merges","archive_url":"https://api.github.com/repos/jhamman/xray/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jhamman/xray/downloads","issues_url":"https://api.github.com/repos/jhamman/xray/issues{/number}","pulls_url":"https://api.github.com/repos/jhamman/xray/pulls{/number}","milestones_url":"https://api.github.com/repos/jhamman/xray/milestones{/number}","notifications_url":"https://api.github.com/repos/jhamman/xray/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jhamman/xray/labels{/name}","releases_url":"https://api.github.com/repos/jhamman/xray/releases{/id}","created_at":"2014-02-25T18:09:57Z","updated_at":"2015-04-07T17:39:11Z","pushed_at":"2015-12-02T21:01:33Z","git_url":"git://github.com/jhamman/xray.git","ssh_url":"git@github.com:jhamman/xray.git","clone_url":"https://github.com/jhamman/xray.git","svn_url":"https://github.com/jhamman/xray","homepage":null,"size":5535,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"xray:master","ref":"master","sha":"76d15b27974b10eae88f343ab568deb815073323","user":{"login":"xray","id":7505795,"avatar_url":"https://avatars.githubusercontent.com/u/7505795?v=3","gravatar_id":"","url":"https://api.github.com/users/xray","html_url":"https://github.com/xray","followers_url":"https://api.github.com/users/xray/followers","following_url":"https://api.github.com/users/xray/following{/other_user}","gists_url":"https://api.github.com/users/xray/gists{/gist_id}","starred_url":"https://api.github.com/users/xray/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xray/subscriptions","organizations_url":"https://api.github.com/users/xray/orgs","repos_url":"https://api.github.com/users/xray/repos","events_url":"https://api.github.com/users/xray/events{/privacy}","received_events_url":"https://api.github.com/users/xray/received_events","type":"Organization","site_admin":false},"repo":{"id":13221727,"name":"xray","full_name":"xray/xray","owner":{"login":"xray","id":7505795,"avatar_url":"https://avatars.githubusercontent.com/u/7505795?v=3","gravatar_id":"","url":"https://api.github.com/users/xray","html_url":"https://github.com/xray","followers_url":"https://api.github.com/users/xray/followers","following_url":"https://api.github.com/users/xray/following{/other_user}","gists_url":"https://api.github.com/users/xray/gists{/gist_id}","starred_url":"https://api.github.com/users/xray/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xray/subscriptions","organizations_url":"https://api.github.com/users/xray/orgs","repos_url":"https://api.github.com/users/xray/repos","events_url":"https://api.github.com/users/xray/events{/privacy}","received_events_url":"https://api.github.com/users/xray/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/xray/xray","description":"N-D labeled arrays and datasets in Python","fork":false,"url":"https://api.github.com/repos/xray/xray","forks_url":"https://api.github.com/repos/xray/xray/forks","keys_url":"https://api.github.com/repos/xray/xray/keys{/key_id}","collaborators_url":"https://api.github.com/repos/xray/xray/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/xray/xray/teams","hooks_url":"https://api.github.com/repos/xray/xray/hooks","issue_events_url":"https://api.github.com/repos/xray/xray/issues/events{/number}","events_url":"https://api.github.com/repos/xray/xray/events","assignees_url":"https://api.github.com/repos/xray/xray/assignees{/user}","branches_url":"https://api.github.com/repos/xray/xray/branches{/branch}","tags_url":"https://api.github.com/repos/xray/xray/tags","blobs_url":"https://api.github.com/repos/xray/xray/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/xray/xray/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/xray/xray/git/refs{/sha}","trees_url":"https://api.github.com/repos/xray/xray/git/trees{/sha}","statuses_url":"https://api.github.com/repos/xray/xray/statuses/{sha}","languages_url":"https://api.github.com/repos/xray/xray/languages","stargazers_url":"https://api.github.com/repos/xray/xray/stargazers","contributors_url":"https://api.github.com/repos/xray/xray/contributors","subscribers_url":"https://api.github.com/repos/xray/xray/subscribers","subscription_url":"https://api.github.com/repos/xray/xray/subscription","commits_url":"https://api.github.com/repos/xray/xray/commits{/sha}","git_commits_url":"https://api.github.com/repos/xray/xray/git/commits{/sha}","comments_url":"https://api.github.com/repos/xray/xray/comments{/number}","issue_comment_url":"https://api.github.com/repos/xray/xray/issues/comments{/number}","contents_url":"https://api.github.com/repos/xray/xray/contents/{+path}","compare_url":"https://api.github.com/repos/xray/xray/compare/{base}...{head}","merges_url":"https://api.github.com/repos/xray/xray/merges","archive_url":"https://api.github.com/repos/xray/xray/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/xray/xray/downloads","issues_url":"https://api.github.com/repos/xray/xray/issues{/number}","pulls_url":"https://api.github.com/repos/xray/xray/pulls{/number}","milestones_url":"https://api.github.com/repos/xray/xray/milestones{/number}","notifications_url":"https://api.github.com/repos/xray/xray/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/xray/xray/labels{/name}","releases_url":"https://api.github.com/repos/xray/xray/releases{/id}","created_at":"2013-09-30T17:21:10Z","updated_at":"2015-11-30T09:39:08Z","pushed_at":"2015-12-02T21:20:36Z","git_url":"git://github.com/xray/xray.git","ssh_url":"git@github.com:xray/xray.git","clone_url":"https://github.com/xray/xray.git","svn_url":"https://github.com/xray/xray","homepage":"http://xray.readthedocs.org","size":5818,"stargazers_count":286,"watchers_count":286,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":75,"mirror_url":null,"open_issues_count":108,"forks":75,"open_issues":108,"watchers":286,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/xray/xray/pulls/668"},"html":{"href":"https://github.com/xray/xray/pull/668"},"issue":{"href":"https://api.github.com/repos/xray/xray/issues/668"},"comments":{"href":"https://api.github.com/repos/xray/xray/issues/668/comments"},"review_comments":{"href":"https://api.github.com/repos/xray/xray/pulls/668/comments"},"review_comment":{"href":"https://api.github.com/repos/xray/xray/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/xray/xray/pulls/668/commits"},"statuses":{"href":"https://api.github.com/repos/xray/xray/statuses/1a4adef9c52f79f24fbb3f28306b9f70c5abe280"}}}}