title: Proper way to winsorize but ignore nan in Python
body: <p>I am trying to winsorize a pandas series which contains NaNs. Using mask can escape NaNs, but it only escapes NaNs when finding the percentile value, then replaces NaN also with that value, which is NOT what I want.</p>
  
  <p>For example, df is consisted of 1, 2, ..., 98, 99, Inf, NaN. For a (0.01, 0.01) winsorization, the result should be 2, 2, 3, 4, ..., 98, 99, 99, NaN.</p>
  
  <p>Using winsorize directly yields 2, 2, 3, 4, ..., 98, 99, 99. I tried to mask NaNs first, then winsorize, and at last replace the number by NaN where it is originally NaN:</p>
  
  <pre><code>import numpy as np
  import pandas as pd
  from scipy.stats.mstats import winsorize
  df = pd.DataFrame(list(range(1,99))+[np.Inf, np.NaN])
  np.where(df.isnull(), np.nan, winsorize(np.ma.masked_invalid(df),limits=(0.01,0.01)))
  </code></pre>
  
  <p>However, the result is now 1, 2, 3, ..., 98, 99, 99, NaN. The smallest number 1 is not correctly winsorized and I don't understand why this happens.</p>
  
  <p>The reason why I don't first drop NaNs and then winsorize is that the index needs to be kept. This is part of a large dataset and other variables for that observation is not missing.</p>
  
  <p>Is there a way (preferablly elegant) to achieve my goal?</p>