У меня есть относительно большой объект DataFrame (около миллиона строк, сотни столбцов), и я хотел бы кликать выбросы в каждом столбце по группе. Под "клип-выбросами для каждого столбца по группе" я имею в виду - вычислить кванты 5% и 95% для каждого столбца в группе и значения клипа вне этого диапазона квантилей.
Здесь настройка, которую я сейчас использую:
def winsorize_series(s):
q = s.quantile([0.05, 0.95])
if isinstance(q, pd.Series) and len(q) == 2:
s[s < q.iloc[0]] = q.iloc[0]
s[s > q.iloc[1]] = q.iloc[1]
return s
def winsorize_df(df):
return df.apply(winsorize_series, axis=0)
а затем, с моим DataFrame, который называется features
и индексируется DATE
, я могу сделать
grouped = features.groupby(level='DATE')
result = grouped.apply(winsorize_df)
Это работает, за исключением того, что он очень медленный, предположительно из-за вложенных вызовов apply
: по одному в каждой группе, а затем по одному для каждого столбца в каждой группе. Я попытался избавиться от второго apply
, вычислив квантили для всех столбцов сразу, но застрял, пытаясь порождать каждый столбец другим значением. Есть ли более быстрый способ выполнить эту процедуру?