Repository: pandas-dev/pandas

Issue:
Regression in DataFrameGroupBy.head()
For [this SO question](http://stackoverflow.com/questions/22691010/how-to-print-a-groupby-object) I isolated a regression in `DataFrameGroupBy.head()` between 0.12.0 and 0.13.0.

```
In [1]: df = pd.DataFrame({'A': ['one', 'one', 'two', 'three', 'three', 'one'], 'B': range(6)})
```

In 0.12.0:

```
In [2]: df.groupby('A').head()
Out[2]: 
             A  B
A                
one   0    one  0
      1    one  1
      5    one  5
three 3  three  3
      4  three  4
two   2    two  2
```

which effectively returns the rows of the underlying `.obj` sorted by group. In 0.13.0:

```
In [2]: df.groupby('A').head()
Out[2]: 
             A  B
A                
one   0    one  0
      1    one  1
two   2    two  2
three 3  three  3
      4  three  4
one   5    one  5

[6 rows x 2 columns]
```

which returns the rows of the underlying `.obj` in their original order. The former is more intuitive.

Regression in DataFrameGroupBy.head()
For [this SO question](http://stackoverflow.com/questions/22691010/how-to-print-a-groupby-object) I isolated a regression in `DataFrameGroupBy.head()` between 0.12.0 and 0.13.0.

```
In [1]: df = pd.DataFrame({'A': ['one', 'one', 'two', 'three', 'three', 'one'], 'B': range(6)})
```

In 0.12.0:

```
In [2]: df.groupby('A').head()
Out[2]: 
             A  B
A                
one   0    one  0
      1    one  1
      5    one  5
three 3  three  3
      4  three  4
two   2    two  2
```

which effectively returns the rows of the underlying `.obj` sorted by group. In 0.13.0:

```
In [2]: df.groupby('A').head()
Out[2]: 
             A  B
A                
one   0    one  0
      1    one  1
two   2    two  2
three 3  three  3
      4  three  4
one   5    one  5

[6 rows x 2 columns]
```

which returns the rows of the underlying `.obj` in their original order. The former is more intuitive.



Discussion:
This in master, looks correct to me and does not include the grouping coumn either)

```
In [2]: df.groupby('A').head()
Out[2]: 
       A  B
0    one  0
1    one  1
2    two  2
3  three  3
4  three  4
5    one  5

[6 rows x 2 columns]
```

As I note in my answer, the existence of `head()` on a `GroupBy` is a little confusing. As I think about it, I'm not sure whether it's better to have it show the underlying object or a special re-sorted view.

OK, I can live with that. Closing.

I don't know if it is worth to bikeshed over, but I think we should then at least update the docstring, so marked it as a DOC issue (https://github.com/pydata/pandas/blob/master/pandas/core/groupby.py#L790)
- clarify that it returns "Returns first n rows of each group _in original order_."?
- that it is equivalent to `.apply(lambda x: x.head(n))` is no longer true (that was the previous behaviour)
- the example uses `as_index=False`, while the docs say it does ignore `as_index`

fair enough to make doc string consistent

This in master, looks correct to me and does not include the grouping coumn either)

```
In [2]: df.groupby('A').head()
Out[2]: 
       A  B
0    one  0
1    one  1
2    two  2
3  three  3
4  three  4
5    one  5

[6 rows x 2 columns]
```

As I note in my answer, the existence of `head()` on a `GroupBy` is a little confusing. As I think about it, I'm not sure whether it's better to have it show the underlying object or a special re-sorted view.

OK, I can live with that. Closing.

I don't know if it is worth to bikeshed over, but I think we should then at least update the docstring, so marked it as a DOC issue (https://github.com/pydata/pandas/blob/master/pandas/core/groupby.py#L790)
- clarify that it returns "Returns first n rows of each group _in original order_."?
- that it is equivalent to `.apply(lambda x: x.head(n))` is no longer true (that was the previous behaviour)
- the example uses `as_index=False`, while the docs say it does ignore `as_index`

fair enough to make doc string consistent


Resolving patch:
diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py
--- a/pandas/core/groupby/groupby.py
+++ b/pandas/core/groupby/groupby.py
@@ -2326,8 +2326,9 @@ def head(self, n=5):
         """
         Return first n rows of each group.
 
-        Essentially equivalent to ``.apply(lambda x: x.head(n))``,
-        except ignores as_index flag.
+        Similar to ``.apply(lambda x: x.head(n))``, but it returns a subset of rows
+        from the original DataFrame with original index and order preserved
+        (``as_index`` flag is ignored).
 
         Returns
         -------
@@ -2338,10 +2339,6 @@ def head(self, n=5):
 
         >>> df = pd.DataFrame([[1, 2], [1, 4], [5, 6]],
         ...                   columns=['A', 'B'])
-        >>> df.groupby('A', as_index=False).head(1)
-           A  B
-        0  1  2
-        2  5  6
         >>> df.groupby('A').head(1)
            A  B
         0  1  2
@@ -2357,8 +2354,9 @@ def tail(self, n=5):
         """
         Return last n rows of each group.
 
-        Essentially equivalent to ``.apply(lambda x: x.tail(n))``,
-        except ignores as_index flag.
+        Similar to ``.apply(lambda x: x.tail(n))``, but it returns a subset of rows
+        from the original DataFrame with original index and order preserved
+        (``as_index`` flag is ignored).
 
         Returns
         -------
@@ -2373,10 +2371,6 @@ def tail(self, n=5):
            A  B
         1  a  2
         3  b  2
-        >>> df.groupby('A').head(1)
-           A  B
-        0  a  1
-        2  b  1
         """
         self._reset_group_selection()
         mask = self._cumcount_array(ascending=False) < n


Test patch: