Фильтровать строки внутри оконной функции в Python Polars?

Мне нужно вычислить индекс Херфиндаля-Хиршмана («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 отдельных рынков, поэтому о том, чтобы сделать это вручную, не может быть и речи.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Из суммы квадратов можно вынести знаменатель:

.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.

Ага! Как обычно, немного творческой арифметики в помощь :). Спасибо.

epistemetrica 27.08.2024 17:21

математические решения действительно лучшие

Roman Pekar 27.08.2024 17:23

Другие вопросы по теме