Сложная тройная сумма в фрейме данных pandas

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

import pandas as pd

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

df = pd.DataFrame(data)

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

$$\sum_{k=\not= i}\sum_{j\not= i,k} f(k,j,i), \ \ f(k,j,i):=\frac{\theta_j+\ theta_i}{\theta_i+\theta_j+\theta_k\cdot \theta_i}$$,

где $k,j$ — это Student_ID внутри одного и того же Race_ID, а $theta_i$ — это theta, где Student_ID равно i. Например, для Race_ID $=1$ мы имеем

функция для Student_ID $= 3$: $f(5,4,3)+f(4,5,3)=124/175=0.708577$

функция для Student_ID $= 5$: $f(3,4,5)+f(4,3,5)=232/341=0.680352$

функция для Student_ID $= 4$: $f(3,5,4)+f(5,3,4)=97/154=0.629870$

Вот что я пробовал, но, похоже, это не работает, а также кажется очень медленным, когда фрейм данных большой:

def compute_sum(row, df):
  Race_ID = row['Race_ID']
  n_RaceID = df.groupby('Race_ID')['Student_ID'].nunique()[Race_ID]
  theta_i_values = df[(df['Race_ID'] == Race_ID) & (df['Student_ID'] == row['Student_ID'])]['theta'].values
  theta_values = df[(df['Race_ID'] == Race_ID) & (df['Student_ID'] != row['Student_ID'])]['theta'].values
  sum_ = sum([((theta_values[j] + theta_i_values[i]) / (theta_i_values[i] + theta_values[j] + theta_values[k] * theta_i_values[i])) for i in range(len(theta_i_values)) for k in range(len(theta_values)) if k != i for j in range(len(theta_values)) if j != i and j != k])
  return sum_

df['feature'] = df.apply(lambda row: compute_sum(row, df), axis=1)

Пожалуйста, дважды проверьте свои расчеты, они кажутся неверными для учащихся 5 и 4. Одна из основных проблем в вашем подходе заключается в том, что вы можете иметь один и тот же идентификатор учащегося для разных рас, и у них разная тета.

mozway 10.07.2024 09:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Одним из вариантов может быть создание функции для работы с каждой группой с помощью groupby.apply , set идентификаторов учащихся и itertools.permutations:

from itertools import permutations

def f(tk, tj, ti):
    return (tj+ti)/(tj+ti+tk*ti)

def compute(g):
    thetas = dict(zip(g['Student_ID'], g['theta']))
    ids = set(g['Student_ID'])
    
    return pd.Series((sum(f(thetas[k], thetas[j], thetas[i])
                             for (k,j) in permutations(S, 2))
                      for i in g['Student_ID'] for S in [ids-{i}]),
                     index=g.index)

df['feature'] = (df.groupby('Race_ID', group_keys=False)
                   .apply(compute, include_groups=False)
                )

Выход:

    Race_ID  Student_ID  theta    feature
0         1           3      3   0.708571
1         1           5      4   0.680352
2         1           4      6   0.629870
3         2           1      8   3.307021
4         2           2      9   3.213902
5         2           3      2   4.770714
6         2           4     12   2.995137
7         2           5      4   3.890607
8         3           4      9   1.142857
9         3           3      0   2.000000
10        3           7      6   1.100000
11        4           2      5   0.000000
12        4           3      2   0.000000
13        5           9      5   8.129834
14        5          10     30   6.170815
15        5           2      3   8.695333
16        5           3      2   9.249267
17        5           6      1  10.557860
18        5           5     50   5.669121

большое спасибо! Только что проверил свои вычисления, они были неправильными, обновлено, большое спасибо за вашу помощь!

Ishigami 10.07.2024 10:06

Мое решение

импортировать панд как pd

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

df = pd.DataFrame(data)

# Function to calculate the feature
def calculate_feature(row):
    race_id = row['Race_ID']
    student_id = row['Student_ID']
    theta_i = row['theta']
    
    race_data = df[df['Race_ID'] == race_id]
    feature_sum = 0
    
    for index, data in race_data.iterrows():
        if data['Student_ID'] != student_id:
            theta_j = data['theta']
            for index2, data2 in race_data.iterrows():
                if data2['Student_ID'] != student_id and data2['Student_ID'] != data['Student_ID']:
                    theta_k = data2['theta']
                    feature_sum += (theta_j + theta_i) / (theta_i + theta_j + (theta_k * theta_i))
    
    return feature_sum

# Applying the function to create the new column 'feature'
df['feature'] = df.apply(calculate_feature, axis=1)

# Displaying the updated DataFrame
print(df)

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