WIP/ENH: Weightby
closes #10030

this is on top of #14483 

provides a groupby-like API to weighted calculations. The weights are lazily calculated and cached.
Deprecates the ``weights`` parameter to ``.sample()``, and implements all of this logic inside ``.weightby``.

TODO:
- only sum/mean are implemented ATM, but logic for other ops (std, var, kurt, skew) are straightforward.
- no logic ATM for a ``.groupby(...).weightby(...)`` or ``.groupby(...).rolling(...)``, but should be a straightforward enhancement.
- easy enhancement to add 'other' weight calculations at some point (just adding args to the ``.weightby`` constructor), see [here](https://github.com/pandas-dev/pandas/issues/10030#issuecomment-238324993)

```
In [1]: df = DataFrame({'A': [1, 2, 3, 4],
   ...:                 'B': [1, 2, 3, 4]})
   ...: 

In [2]: df
Out[2]: 
   A  B
0  1  1
1  2  2
2  3  3
3  4  4

In [3]: df.weightby('A').B.sum()
Out[3]: 3.0

In [4]: df.weightby('A').sum()
Out[4]: 
B    3.0
dtype: float64

In [5]: df.weightby('A').sample(n=2)
Out[5]: 
   B
3  4
1  2

In [7]: w = df.weightby('A')

In [8]: w.mean()
Out[8]: 
B    0.75
dtype: float64

In [9]: w._weights
Out[9]: array([ 0.1,  0.2,  0.3,  0.4])
```