Получить значение квантиля переменной для каждой группы

#pandas #quantile

#pandas #квантиль

Вопрос:

У меня есть данные, которые классифицируются по группам с заданным процентом квантиля для каждой группы. Я хочу создать пороговое значение для каждой группы, которое разделяет все значения внутри группы на основе процента квантиля. Итак, если одна группа имеет q = 0,8, я хочу, чтобы наименьшие значения 80% были равны 1, а верхние значения 20% равны 0.

Итак, учитывая такие данные:

Данные

Я хочу, чтобы объекты 1, 2 и 5 получили результат 1, а остальные 3 результата 0. В общей сложности мои данные состоят из 7.000.000 строк с 14.000 группами. Я пытался сделать это с помощью groupby.квантиль, но поэтому мне нужна постоянная мера квантиля, тогда как мои данные отличаются для каждой группы.

Ответ №1:

Настройка:

 num = 7_000_000
grp_num = 14_000
qua = np.around(np.random.uniform(size=grp_num), 2)
df = pd.DataFrame({
    "Group": np.random.randint(low=0, high=grp_num, size=num),
    "Quantile": 0.0,
    "Value": np.random.randint(low=100, high=300, size=num)
}).sort_values("Group").reset_index(0, drop=True)

def func(grp):
    grp["Quantile"] = qua[grp.Group]
    return grp

df = df.groupby("Group").apply(func)
  

Ответ: (Это в основном цикл for, поэтому для повышения производительности вы можете попробовать применить numba к этому)

 def func2(grp):
    return grp.Value < grp.Value.quantile(grp.Quantile.iloc[0])

df["result"] = df.groupby("Group").apply(func2).reset_index(0, drop=True)
print(df)
  

Выводит:

          Group  Quantile  Value  result
0            0      0.33    156       1
1            0      0.33    259       0
2            0      0.33    166       1
3            0      0.33    183       0
4            0      0.33    111       1
...        ...       ...    ...     ...
6999995  13999      0.83    194       1
6999996  13999      0.83    227       1
6999997  13999      0.83    215       1
6999998  13999      0.83    103       1
6999999  13999      0.83    115       1

[7000000 rows x 4 columns]
CPU times: user 14.2 s, sys: 362 ms, total: 14.6 s
Wall time: 14.7 s