Суммирование перестановок в фрейме данных Pandas растет суперэкспоненциально

У меня есть фрейм данных pandas, который выглядит так

import pandas as pd

data = {
  "Race_ID": [2,2,2,2,2,5,5,5,5,5,5],
  "Student_ID": [1,2,3,4,5,9,10,2,3,6,5],
  "theta": [8,9,2,12,4,5,30,3,2,1,50]
}

df = pd.DataFrame(data)

И я хотел бы создать новый столбец df['feature'] следующим методом: для каждого Race_ID предположим, что Student_ID равен i, тогда мы определяем функцию как

def f(thetak, thetaj, thetai, *theta):
  prod = 1;
  for t in theta:
    prod = prod * t;
  return ((thetai + thetaj) / (thetai + thetaj + thetai * thetak)) * prod 

где k,j,l — это Student_ID внутри одного и того же Race_ID, такие что k =/= i, j=/=i,k, l=/=k,j,i и theta_i — это theta, где Student_ID равно i. Например, для Race_ID =2, Student_ID =1 у нас есть функция, равная

f(2,3,1,4,5)+f(2,3,1,5,4)+f(2,4,1,3,5)+f(2,4,1,5,3 )+f(2,5,1,3,4)+f(2,5,1,4,3)+f(3,2,1,4,5)+f(3,2,1,5 ,4)+f(3,4,1,2,5)+f(3,4,1,5,2)+f(3,5,1,2,4)+f(3,5,1 ,4,2)+f(4,2,1,3,5)+f(4,2,1,5,3)+f(4,3,1,2,5)+f(4,3 ,1,5,2)+f(4,5,1,2,3)+f(4,5,1,3,2)+f(5,2,1,3,4)+f(5 ,2,1,4,3)+f(5,3,1,2,4)+f(5,3,1,4,2)+f(5,4,1,2,3)+f (5,4,1,3,2)

что равно 299,1960138012742.

Но, как быстро понимаешь, количество членов в сумме растет суперэкспоненциально с увеличением количества студентов в забеге: если в забеге n учеников, то их (n-1)! условия в сумме.

К счастью, благодаря свойству симметрии f мы можем сократить количество членов до простых (n-1)(n-2), отметив следующее:

Пусть заданы i,j,k и 1,2,3 (например, ради) отличаются от i,j,k (т.е. 1,2,3 находятся в *arg). Тогда f(k,j,i,1,2,3) = f(k,j,i,1,3,2) = f(k,j,i,2,1,3) = f(k, j,i,2,3,1) = f(k,j,i,3,1,2) = f(k,j,i,3,2,1). Следовательно, мы можем уменьшить количество членов, если просто вычислим любой из членов, а затем умножим его на (n-3)!

Так, например, для Race_ID =5, Student_ID =9 нужно было бы суммировать 5!=120 членов, но, используя указанное выше свойство симметрии, нам нужно суммировать только 5x4 = 20 членов (5 вариантов для k, 4 варианта для i и 1 (неединственный выбор) для l), а именно

f(2,3,9,5,6,10)+f(2,5,9,3,6,10)+f(2,6,9,3,5,10)+f(2,10 ,9,3,5,6)+f(3,2,9,5,6,10)+f(3,5,9,3,6,10)+f(3,6,9,2, 5,10)+f(3,10,9,2,5,6)+f(5,2,9,3,6,10)+f(5,3,9,2,6,10)+ f(5,6,9,2,3,10)+f(5,10,9,2,3,6)+f(6,2,9,3,5,10)+f(6,3 ,9,2,5,10)+f(6,5,9,2,3,10)+f(6,10,9,2,3,5)+f(10,2,9,3, 5,6)+f(10,3,9,2,5,6)+f(10,5,9,2,3,6)+f(10,6,9,2,3,5)

и показатель для ученика 9 в забеге 5 будет равен указанной выше сумме, умноженной на 3! = 53588,197759

Итак, вопрос: как мне записать сумму для приведенного выше кадра данных? Я вычислил функции вручную для проверки, и желаемый результат выглядит так:

import pandas as pd

data = {
  "Race_ID": [2,2,2,2,2,5,5,5,5,5,5],
  "Student_ID": [1,2,3,4,5,9,10,2,3,6,5],
  "theta": [8,9,2,12,4,5,30,3,2,1,50],
  "feature": [299.1960138012742, 268.93506341257876, 634.7909309816431, 204.18901708653254, 483.7234700875771, 53588.197759, 9395.539167178009, 78005.26224935807, 92907.8753942894, 118315.38359654899, 5600.243276203378]
}

df = pd.DataFrame(data)

Большое спасибо.

Вы спрашиваете, как написать функцию Python, которая вычисляет второе математическое выражение для вашей функции f?

Emmanuel Murairi 17.07.2024 19:47

@EmmanuelMurairi Да, чтобы мы могли сэкономить вычисления и вычислить меньше терминов

Ishigami 17.07.2024 21:43

@ScottBoston Да, для RaceID = 2 длина *theta равна 2, а для RaceID = 5 длина *theta равна 3. В общем, для расы с n учениками длина *theta равна n-3. .

Ishigami 18.07.2024 04:51
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
181
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Этот код можно настроить и сделать быстрее:

import pandas as pd
import numpy as np
from itertools import permutations

data = {
  "Race_ID": [2,2,2,2,2,5,5,5,5,5,5],
  "Student_ID": [1,2,3,4,5,9,10,2,3,6,5],
  "theta": [8,9,2,12,4,5,30,3,2,1,50]
}

df = pd.DataFrame(data)

Определить функции:

def f(thetak, thetaj, thetai, *theta):
  prod = 1;
  for t in theta:
    prod *= t;
  return ((thetai + thetaj) / (thetai + thetaj + thetai * thetak)) * prod 


def student_race_theta(si, thetas, student):
    total = 0
    for ts in permutations(range(1, len(si)+1)):
        if si.iloc[ts[2]-1] == student:
            thetak, thetaj, thetai, *theta = [thetas.iloc[i-1] for i in ts]
            total += f(thetak, thetaj, thetai, *theta)
    return total

def fxs(x):
    s = pd.Series()
    for i, r in x.iterrows():
        s[i] = student_race_theta(x['Student_ID'], x['theta'], r['Student_ID'])
    return s
    
df['feature'] = df.groupby('Race_ID', group_keys=False)\
                  [['Race_ID', 'Student_ID', 'theta']].apply(fxs)

print(df)

Выход:

    Race_ID  Student_ID  theta        feature
0         2           1      8     299.196014
1         2           2      9     268.935063
2         2           3      2     634.790931
3         2           4     12     204.189017
4         2           5      4     483.723470
5         5           9      5   53588.197759
6         5          10     30    9395.539167
7         5           2      3   78005.262249
8         5           3      2   92907.875394
9         5           6      1  118315.383597
10        5           5     50    5600.243276

Я не совпадаю с вашей строкой Race_ID 5, Student_iD 9, но все остальные значения совпадают.

Scott Boston 20.07.2024 04:32

Только что проверил свои расчеты, вы были правы, я обновил число. Огромное спасибо, вы гений!

Ishigami 20.07.2024 14:24

Спасибо. Никакого гения, просто какое-то время работал с Python и пандами. Я уверен, что это можно сделать лучше. Приятного кодирования!

Scott Boston 20.07.2024 15:41

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

Найдите значение в столбце, который содержит список, возьмите другое значение из следующего столбца и поместите его в первую таблицу в новый столбец
Python pandas read_sas с параметром размера фрагмента завершается с ошибкой из-за несоответствия индекса
Как я могу заполнить значение на основе другого категориального столбца
Что означает: приведение данных Pandas к numpy dtype объекта. Проверьте входные данные с помощью np.asarray(data) и как это можно решить?
Как обобщить фрейм данных в пандах на основе значений
Отсутствует модуль Sklearn и вы не знаете, что использовать вместо него?
Как я могу эффективно фильтровать и агрегировать данные в Pandas DataFrame с несколькими условиями?
Существует ли идиома Pandas для чтения файла CSV с категориальными данными, имеющими варианты написания?
Разделить столбец данных pandas на несколько на основе текстовых значений
Как использовать условие для нескольких столбцов в Pandas?