У меня есть фрейм данных 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)
и у меня есть функция f(thetai, *theta) = thetai ** 2 + the other thetas in the same race
, которую я хочу применить к столбцу theta
в фрейме данных, сгруппированному по Race_ID
, и создать новый столбец с именем feature
.
Итак, у нас есть
Для ученика 1 в гонке 2 значение равно 8^2 + 9+2+12+4.
Для ученика 2 в гонке 2 значение равно 9^2 + 8+2+12+4.
Для ученика 3 в гонке 2 значение равно 2^2 + 8+9+12+4.
и т. д.
Я знаю о методах groupby
и apply
, но не знаю, как их применять, когда количество аргументов может меняться.
Итак, желаемый результат выглядит так
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],
"fearure": [91,107,37,167,47,111,961,97,93,91,2541]
}
df = pd.DataFrame(data)
Обновлено: моя фактическая функция f
для моей проблемы на самом деле намного сложнее, я просто использовал приведенный здесь пример, чтобы продемонстрировать основное препятствие, а именно проблему с переменным аргументом. Вот моя фактическая функция f:
def integrand(xi, thetai, *theta):
S = 0
for tj in theta:
prod = 1
for t in theta:
if abs(t - tj) < 1e-10:
continue
prod = prod * (1 - norm.cdf(xi + thetai - t))
S = S + norm.cdf(xi + thetai - tj) * prod
return S * norm.pdf(xi)
def f(thetai, *theta):
return (integrate.quad(integrand, -np.inf, np.inf, args=(thetai, *theta)))[0]
Просто создайте промежуточный столбец сумм остальных тэт.
theta_sum = df.groupby("Race_ID").sum()["theta"].to_dict()
# (theta sum of race_id) - self theta
df["theta_feature"] = df.apply(
lambda x: theta_sum[x["Race_ID"]] - x["theta"], axis=1
)
df["feature"] = df.apply(
lambda x: x["theta"] ** 2 + x["theta_feature"], axis=1
)
а затем, если вам не нужен нежелательный столбец, вы можете просто удалить его с помощью
df.drop(columns = "theta_feature", inplace=True)
Обновлено: - Чтобы передать теты в функцию (которая даст другой результат для столбца feature
, поскольку функция изначально не описана, вы можете сделать apply
со следующим: -
def calc_grpd_thetas(x):
_df = df[(df['Race_ID'] == x["Race_ID"]) & (df.index != x.name)]
thetas = list(_df['theta'])
return f(x["theta"], *thetas)
df["feature"] = df.apply(calc_grpd_thetas, axis=1)
что принесет вам это
Привет, не могли бы вы включить функцию integrand
в свое редактирование?
Привет @dydev, я сделал, пожалуйста, посмотрите редактирование, большое спасибо ``` def integrand(xi, thetai, *theta): S = 0 для tj в тета: prod = 1 для t в тета: if abs(t - tj) < 1e-10: продолжить prod = prod * (1 -normal.cdf(xi + thetai - t)) S = S +normal.cdf(xi + thetai - tj) * prod return S *normal.pdf( xi) ```
@Ishigami Я отредактировал сообщение, чтобы передать теты в функцию, как описано. Надеюсь, это было то, что вы искали.
Используйте groupby.transform со специальной функцией:
def f(t):
# get sum of all
s = t.sum()
# sum of all - self + self^2
# = sum of others + self^2
return t.rsub(s).add(t**2)
df['feature'] = df.groupby('Race_ID')['theta'].transform(f)
Это эквивалентно тому, чтобы взять сумму и добавить theta*(theta-1)
:
df['feature'] = (df.groupby('Race_ID')['theta']
.transform(lambda t: t*(t-1)+t.sum())
)
Альтернативно, с помощью transform('sum')
и после этого выполните коррекцию.
df['feature'] = (df.groupby('Race_ID')['theta']
.transform('sum')
.sub(df['theta'])
.add(df['theta']**2)
)
Выход:
Race_ID Student_ID theta feature
0 2 1 8 91
1 2 2 9 107
2 2 3 2 37
3 2 4 12 167
4 2 5 4 47
5 5 9 5 111
6 5 10 30 961
7 5 2 3 97
8 5 3 2 93
9 5 6 1 91
10 5 5 50 2541
Привет @mozway, спасибо за ответ, но моя фактическая функция f(thetai, *theta) на самом деле намного сложнее (это интеграл с использованием scipy.integrate.quad), и я просто использовал приведенный здесь пример, чтобы продемонстрировать основные препятствием, а именно проблемой переменного аргумента. Я отредактировал задачу, включив в нее свою настоящую функцию f, большое спасибо за вашу помощь.
Привет @dydev, спасибо за ответ, но моя фактическая функция f(thetai, *theta) на самом деле намного сложнее (это интеграл с использованием scipy.integrate.quad), и я просто использовал приведенный здесь пример, чтобы продемонстрировать основные препятствием, а именно проблемой переменного аргумента. Я отредактировал задачу, включив в нее свою настоящую функцию f, большое спасибо за вашу помощь.