Мне нужно вычислить индекс Херфиндаля-Хиршмана («HHI», сумма квадратов рыночных долей), но не учитывая фирму, представленную в строке. Вот пример:
df = (pl.DataFrame({
'year':(2023, 2023, 2023, 2024, 2024, 2024),
'firm':('A', 'B', 'C', 'A', 'B', 'C'),
'volume':(20, 50, 3, 25, 13, 5)
})
.with_columns(
sum = pl.col('volume').sum().over('year'),
leaveout_sum = (pl.col('volume').sum().over('year'))-(pl.col('volume'))
)
.with_columns(
share = (pl.col('volume')/pl.col('sum'))*100
)
.with_columns(
hhi = (pl.col('share')**2).sum().over('year').round()
))
Что дает:
┌──────┬──────┬────────┬─────┬──────────────┬───────────┬────────┐
│ year ┆ firm ┆ volume ┆ sum ┆ leaveout_sum ┆ share ┆ hhi │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ i64 ┆ i64 ┆ i64 ┆ f64 ┆ f64 │
╞══════╪══════╪════════╪═════╪══════════════╪═══════════╪════════╡
│ 2023 ┆ A ┆ 20 ┆ 73 ┆ 53 ┆ 27.39726 ┆ 5459.0 │
│ 2023 ┆ B ┆ 50 ┆ 73 ┆ 23 ┆ 68.493151 ┆ 5459.0 │
│ 2023 ┆ C ┆ 3 ┆ 73 ┆ 70 ┆ 4.109589 ┆ 5459.0 │
│ 2024 ┆ A ┆ 25 ┆ 43 ┆ 18 ┆ 58.139535 ┆ 4429.0 │
│ 2024 ┆ B ┆ 13 ┆ 43 ┆ 30 ┆ 30.232558 ┆ 4429.0 │
│ 2024 ┆ C ┆ 5 ┆ 43 ┆ 38 ┆ 11.627907 ┆ 4429.0 │
└──────┴──────┴────────┴─────┴──────────────┴───────────┴────────┘
Столбец hhi представляет собой обычный индекс HHI, включающий все фирмы на рынке, и я могу вычислить сумму «исключенных» объемов, чтобы получить сумму объемов других фирм за этот год. Например, исключаемый HHI для фирмы A в 2023 году будет равен квадрату 3/53 плюс квадрат 50/53 (т. е. квадратам рыночных долей фирм B и C, если предположить, что фирма A не существует).
Как мне сказать полярникам сделать это? Возможно, есть способ отфильтровать оконную функцию?
Мой реальный набор данных включает почти 800 фирм за 204 месяца для 500 отдельных рынков, поэтому о том, чтобы сделать это вручную, не может быть и речи.
Из суммы квадратов можно вынести знаменатель:
.with_columns(
leaveout_sum = (pl.col.volume.sum().over('year')) - pl.col.volume,
leaveout_sum_of_sq = (pl.col.volume**2).sum().over('year') - pl.col.volume**2
)
.with_columns(
leaveout_hhi = pl.col.leaveout_sum_of_sq / pl.col.leaveout_sum**2
))
Я пропустил фактор * 100
, приведенное выше правильно вычисляет (3/53)^2 + (50/53)^2
для вашего примера, выполнив (3^2 + 50^2) / (50 + 3)^2
.
математические решения действительно лучшие
Ага! Как обычно, немного творческой арифметики в помощь :). Спасибо.