Repository: pandas-dev/pandas

Issue:
PERF: resample with max/min taking slow path
```
In [21]: df = DataFrame(np.random.randn(100000,2),index=date_range('20130101',periods=100000,freq='50L'))

In [19]: %timeit df.resample('1s',how=np.max)[0]
1 loops, best of 3: 902 ms per loop
```

mean is ok

```
In [22]: %timeit df.resample('1s',how=np.mean)[0]
100 loops, best of 3: 2.42 ms per loop
```

The way to do this actually is ohlc

```
In [20]: %timeit df.groupby(pd.TimeGrouper('1s'))[0].ohlc()
1000 loops, best of 3: 1.16 ms per loop
```



Discussion:
I was wondering for a second why I hadn't seen this, but I tend to write `how='max'` instead, which seems to be fast-path:

```
>>> %timeit df.resample('1s',how=np.max)[0]
1 loops, best of 3: 1.18 s per loop
>>> %timeit df.resample('1s',how='max')[0]
100 loops, best of 3: 3.42 ms per loop
```

I think this is trivial actually.....

just add here: https://github.com/pydata/pandas/blob/master/pandas/core/groupby.py#L2990 (its not mpicking it up because of the mapping)

can you add some vbenches as well? (for both 'max' and np.max)...just to be sure...

I came here to say that `how='max'` takes the fast path in my code, just like @dsm054 asserts.

@chrisaycock yep...its a 'bug' in that 'np.max' is not translated properly......pretty straightforward to fix...

any PR takers?

I can have a go tonight-- haven't done anything vbenchy, but I can pattern-match relatively well, so as long as it's just "do the same thing as everything else" I should be okay.  But if anyone else is dying to do it, he's welcome to it. :^)

@dsm054 gr8....put in `vb_suite/groupby.py`....add a new sub-section for various test of these 

@jreback: you sure you want the vbench stuff in groupby?  Wouldn't it be more natural in timeseries, with the other resample stuff?

sorry
that's what I meant :)

Looks good so far:

```
-------------------------------------------------------------------------------
Test name                                    | head[ms] | base[ms] |  ratio   |
-------------------------------------------------------------------------------
dataframe_resample_min_numpy                 |   4.0100 | 1271.2740 |   0.0032 |
dataframe_resample_max_numpy                 |   4.4327 | 1280.4783 |   0.0035 |
```

Does count also take the slow path (I believe it does)?

@rockg can you put up an example? this was a very depedent path, e.g.

passing `max` and max (the function) worked, but `np.max` did not as it didn't map properly

This is how it looks on my machine.  It is very convoluted how this ends up getting called.  I'll need to see if I can figure out how to speed this up.

%timeit df.resample('1s',how=np.max)[0]
1 loops, best of 3: 1.99 s per loop
%timeit df.resample('1s', how='max')[0]
100 loops, best of 3: 2.95 ms per loop
%timeit df.resample('1s', how='count')[0]
1 loops, best of 3: 4.3 s per loop

@rockg count is not getting translated to call the correct cython method (related but not identical to the np.max problem)

Does the count issue mean I shouldn't make a PR?  (The code and tests are done, but I accidentally merged it into my github master and I'm not sure how to undo that yet.)

@dsm054 you can just rebase out the merged master

`git fetch upstream/master`
`git rebase -i upstream/master`

then just remove that commit

the count can be a separate issue or if you or @rockg figure it out...can be included here


Resolving patch:
diff --git a/pandas/core/groupby.py b/pandas/core/groupby.py
--- a/pandas/core/groupby.py
+++ b/pandas/core/groupby.py
@@ -2994,7 +2994,9 @@ def _reorder_by_uniques(uniques, labels):
     np.prod: 'prod',
     np.std: 'std',
     np.var: 'var',
-    np.median: 'median'
+    np.median: 'median',
+    np.max: 'max',
+    np.min: 'min'
 }
 
 
diff --git a/vb_suite/timeseries.py b/vb_suite/timeseries.py
--- a/vb_suite/timeseries.py
+++ b/vb_suite/timeseries.py
@@ -243,3 +243,29 @@ def date_range(start=None, end=None, periods=None, freq=None):
           setup, start_date=datetime(2013, 9, 30))
 
 
+#----------------------------------------------------------------------
+# Resampling: fast-path various functions
+
+setup = common_setup + """
+rng = date_range('20130101',periods=100000,freq='50L')
+df = DataFrame(np.random.randn(100000,2),index=rng)
+"""
+
+dataframe_resample_mean_string = \
+    Benchmark("df.resample('1s', how='mean')", setup)
+
+dataframe_resample_mean_numpy = \
+    Benchmark("df.resample('1s', how=np.mean)", setup)
+
+dataframe_resample_min_string = \
+    Benchmark("df.resample('1s', how='min')", setup)
+
+dataframe_resample_min_numpy = \
+    Benchmark("df.resample('1s', how=np.min)", setup)
+
+dataframe_resample_max_string = \
+    Benchmark("df.resample('1s', how='max')", setup)
+
+dataframe_resample_max_numpy = \
+    Benchmark("df.resample('1s', how=np.max)", setup)
+


Test patch: