'Construct a Factor returns a winsorized row. Winsorizing changes values
ranked less than the minimum percentile to to value at the minimum
percentile. Similarly, values ranking above the maximum percentile will
be changed to the value at the maximum percentile. This is useful
when limiting the impact of extreme values.
If ``mask`` is supplied, ignore values where ``mask`` returns False
when computing row means and standard deviations, and output NaN
anywhere the mask is False.
If ``groupby`` is supplied, compute by partitioning each row based on
the values produced by ``groupby``, winsorizing the partitioned arrays,
and stitching the sub-results back together.
Parameters
min_percentile: float, int
Entries with values at or below this percentile will be replaced
with the (len(inp) * min_percentile)th lowest value. If low values
should not be clipped, use 0.
max_percentile: float, int
Entries with values at or above this percentile will be replaced
with the (len(inp) * max_percentile)th lowest value. If high
values should not be clipped, use 1.
mask : zipline.pipeline.Filter, optional
A Filter defining values to ignore when winsorizing.
groupby : zipline.pipeline.Classifier, optional
A classifier defining partitions over which to winsorize.
Returns
winsorized : zipline.pipeline.Factor
A Factor producing a winsorized version of self.
Examples
.. code-block:: python
price = USEquityPricing.close.latest
columns={
\'PRICE\': price,
\'WINSOR_1: price.winsorize(
min_percentile=0.25, max_percentile=0.75
\'WINSOR_2\': price.winsorize(
min_percentile=0.50, max_percentile=1.0
\'WINSOR_3\': price.winsorize(
min_percentile=0.0, max_percentile=0.5
Given a pipeline with columns, defined above, the result for a
given day could look like:
\'PRICE\' \'WINSOR_1\' \'WINSOR_2\' \'WINSOR_3\'
Asset_1    1        2          4          3
Asset_2    2        2          4          3
Asset_3    3        3          4          3
Asset_4    4        4          4          4
Asset_5    5        5          5          4
Asset_6    6        5          5          4
See Also
:func:`scipy.stats.mstats.winsorize`
:meth:`pandas.DataFrame.groupby`'

@expect_types(min_percentile=(int, float), max_percentile=(int, float), mask=(Filter, NotSpecifiedType), groupby=(Classifier, NotSpecifiedType))
@float64_only
def winsorize(self, min_percentile, max_percentile, mask=NotSpecified, groupby=NotSpecified):

    if (not (0.0 <= min_percentile < max_percentile <= 1.0)):
        raise BadPercentileBounds(min_percentile=min_percentile, max_percentile=max_percentile, upper_bound=1.0)
    return GroupedRowTransform(transform=winsorize, transform_args=(min_percentile, max_percentile), factor=self, groupby=groupby, dtype=self.dtype, missing_value=self.missing_value, mask=mask, window_safe=self.window_safe)
