KeyError: 0 # Если у нас есть ключ в виде списка, _check_indexing_error будет возникать после применения функции к кадру данных pandas

У меня есть довольно сложная функция f(featureList), которая принимает на вход список произвольной длины и выдает на выходе другой список такой же длины:

import math
import random
import time

def survivalNormalcdf(x):
    return (1-math.erf(x/math.sqrt(2)))/2

def normalcdf(x):
    return (1+math.erf(x/math.sqrt(2)))/2

def normalpdf(x): 
    return math.exp(-x*x/2)/math.sqrt(2*math.pi)

def abss(p):
    q=[]
    for k in range(len(p)):
        q.append(abs(p[k]))
    return q;

def mult(a,p):
    q=[]
    for k in range(len(p)):
        q.append(a*p[k])
    return q;

def add(a,p):
    q=[]
    for k in range(len(p)):
        q.append(a[k]+p[k])
    return q

def dot(u,v,pp):
    s=0
    for k in range(len(u)):
       s+=u[k]*v[k]*pp[k]
    return s;

def grad(t,pp):
    h=math.sqrt(1/5/(len(pp)+1))
    g=[]

    for k in range(len(pp)):
        g.append(-pp[k])
        beg=t[k] - 10
        end=t[k] + 10
        qq=math.ceil((end-beg)/h)
        for q in range(qq):
            x=beg+q*h
            ss=survivalNormalcdf(x)
            for m in range(len(pp)):
                if k==m:
                    ss*=normalpdf(x-t[m])
                else:
                    ss*=survivalNormalcdf(x-t[m])
            g[k]+=ss*h;
    for k in range(len(pp)):
        g[k]/=pp[k]
    return g

def iint(t,pp):
    h=0.1
    ss=0
    for k in range(1):
        beg=min(min(t),0) - 10
        end=max(max(t),0) + 10
        qq=int((end-beg)/h)
        for q in range(qq):
            x=beg+q*h
            s=1; 
            for m in range(len(pp)):
                s*=survivalNormalcdf(x-t[m])
            ss+=(s-1)*survivalNormalcdf(x)*h
        for k in range(len(pp)):
            ss-=pp[k]*t[k]
    return ss

def f(ppp):
    kk=0
    maxx=ppp[0]
    for k in range(len(ppp)):
        if ppp[k]>maxx:
            kk=k
            maxx=ppp[k]
    pp=ppp[:kk]+ppp[kk+1:]
    
    t=[]
    for k in range(len(pp)):
        t.append(math.sqrt(2*math.log(1/pp[k])))
        
    u=grad(t,pp)
    mm=0
    while mm<=50*len(pp) and sum(abss(grad(t,pp)))>1/10.0**12:
        mm+=1
        if mm%len(pp)==1:
            pass
        s=min(1,1/sum(abss(u)))
        cnt=0
        while dot(u, grad(add(t,mult(s,u)),pp),pp)>0 and s*sum(abss(u))<len(u):
            s*=2
            cnt+=1
        a=0
        b=s
        beg=a
        end=b
        A=dot(u, grad(add(t,mult(a,u)),pp),pp)
        B=dot(u, grad(add(t,mult(b,u)),pp),pp)
        k=0
        while k<20 and abs(A-B)>(1/10.0**12)*max(abs(A),abs(B)):
            mid=(beg+end)/2
            if dot(u, grad(add(t,mult(mid,u)),pp),pp)>0:
                beg=mid
            else:
                end=mid
            
            c=max(beg-(1/10.0**12),min(end+(1/10.0**12),b+(B/(A-B))*(b-a)))
            C=dot(u, grad(add(t,mult(c,u)),pp),pp)
            if abs(a-c)>abs(b-c) and abs(b-c)>0:
                a=b
                A=B
                b=c
                B=C
            else:
                b=a
                B=A
                a=c
                A=C
            if C>0:
                beg=max(beg,c)
            else:
                end=min(end,c)
            k+=1
                
        s=c
            
        oldgrad=grad(t,pp)
        t=add(t,mult(s,u))
        newgrad=grad(t,pp)
        uold=mult(1,u)
        u=mult(1,newgrad)
        if mm%len(pp)!=1:
            u=add(u,mult(dot(newgrad, add(newgrad,mult(-1,oldgrad)),pp)/dot(oldgrad,oldgrad,pp),uold))

    
    ss=sum(abss(grad(t,pp)))
    tt=t[:kk]
    tt.append(0)
    t=tt+t[kk:]
    if ss>1/10.0**12:
        x=str(input("Failed"))
    return t

Так, например, у нас есть

f([0.2,0.1,0.55,0.15]) = [0.7980479577400461, 1.2532153405902076, 0, 0.9944188436386611]

f([0.02167131,0.17349148,0.08438952,0.04143787,0.02589056,0.03866752,0.0461553,0.09212758,0.10879326,0.186921,0.02990676,0.02731904,0.06020158,0.06302721]) = 
[1.174313198960376,
 0.04892832217716259,
 0.4858149215364752,
 0.864373517094786,
 1.0921431988531611,
 0.8989070806156786,
 0.8098127832637683,
 0.4358011113129989,
 0.3387512959281985,
 0,
 1.0239882119094197,
 1.0669265516784823,
 0.671235053100702,
 0.6466856803321204]

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

Class_ID  Date           Student_ID      feature  
1         1/1/2023       3               0.02167131     
1         1/1/2023       4               0.17349148     
1         1/1/2023       6               0.08438952     
1         1/1/2023       8               0.04143787     
1         1/1/2023       9               0.02589056
1         1/1/2023       1               0.03866752     
1         1/1/2023       10              0.0461553                                   
3         17/4/2022      5               0.2     
3         17/4/2022      2               0.1     
3         17/4/2022      3               0.55     
3         17/4/2022      4               0.15     

и я хотел бы применить функцию f(featureList) к столбцу featuregroupbyClass_ID и создать новый столбец с именем New_feature. И вот мой код:

df['New_feature'] = df.groupby('Class_ID', group_keys=False)['feature'].apply(f)

Итак, желаемый результат выглядит так:

df_outcome = pd.read_fwf(io.StringIO("""Class_ID   Date          Student_ID      feature        New_feature
1         1/1/2023       3               0.02167131     2.385963956274992
1         1/1/2023       4               0.17349148     0
1         1/1/2023       6               0.08438952     1.6510552553095719
1         1/1/2023       8               0.04143787     2.054792417419151
1         1/1/2023       9               0.02589056     2.298129663961289
1         1/1/2023       1               0.03866752     2.0916706205231286
1         1/1/2023       10              0.0461553       1.9965409929949391
3         17/4/2022      5               0.2            0.7980479577400461
3         17/4/2022      2               0.1            1.2532153405902076
3         17/4/2022      3               0.55           0
3         17/4/2022      4               0.15           0.9944188436386611"""))

Однако выдает следующую ошибку:

KeyError: 0

The above exception was the direct cause of the following exception: 
# If we have a listlike key, _check_indexing_error will raise

Вот код:

import io
import numpy as np
import pandas as pd
import math

df = pd.read_fwf(io.StringIO("""Class_ID  Date           Student_ID      feature  
1         1/1/2023       3               0.02167131     
1         1/1/2023       4               0.17349148     
1         1/1/2023       6               0.08438952     
1         1/1/2023       8               0.04143787     
1         1/1/2023       9               0.02589056
1         1/1/2023       1               0.03866752     
1         1/1/2023       10              0.0461553                                   
3         17/4/2022      5               0.2     
3         17/4/2022      2               0.1     
3         17/4/2022      3               0.55     
3         17/4/2022      4               0.15"""))     

def survivalNormalcdf(x):
    return (1-math.erf(x/math.sqrt(2)))/2

def normalcdf(x):
    return (1+math.erf(x/math.sqrt(2)))/2

def normalpdf(x): 
    return math.exp(-x*x/2)/math.sqrt(2*math.pi)

def abss(p):
    q=[]
    for k in range(len(p)):
        q.append(abs(p[k]))
    return q;

def mult(a,p):
    q=[]
    for k in range(len(p)):
        q.append(a*p[k])
    return q;

def add(a,p):
    q=[]
    for k in range(len(p)):
        q.append(a[k]+p[k])
    return q

def dot(u,v,pp):
    s=0
    for k in range(len(u)):
       s+=u[k]*v[k]*pp[k]
    return s;

def grad(t,pp):
    h=math.sqrt(1/5/(len(pp)+1))
    g=[]

    for k in range(len(pp)):
        g.append(-pp[k])
        beg=t[k] - 10
        end=t[k] + 10
        qq=math.ceil((end-beg)/h)
        for q in range(qq):
            x=beg+q*h
            ss=survivalNormalcdf(x)
            for m in range(len(pp)):
                if k==m:
                    ss*=normalpdf(x-t[m])
                else:
                    ss*=survivalNormalcdf(x-t[m])
            g[k]+=ss*h;
    for k in range(len(pp)):
        g[k]/=pp[k]
    return g

def iint(t,pp):
    h=0.1
    ss=0
    for k in range(1):
        beg=min(min(t),0) - 10
        end=max(max(t),0) + 10
        qq=int((end-beg)/h)
        for q in range(qq):
            x=beg+q*h
            s=1; 
            for m in range(len(pp)):
                s*=survivalNormalcdf(x-t[m])
            ss+=(s-1)*survivalNormalcdf(x)*h
        for k in range(len(pp)):
            ss-=pp[k]*t[k]
    return ss

def f(ppp):
    kk=0
    maxx=ppp[0]
    for k in range(len(ppp)):
        if ppp[k]>maxx:
            kk=k
            maxx=ppp[k]
    pp=ppp[:kk]+ppp[kk+1:]
    
    t=[]
    for k in range(len(pp)):
        t.append(math.sqrt(2*math.log(1/pp[k])))
        
    u=grad(t,pp)
    mm=0
    while mm<=50*len(pp) and sum(abss(grad(t,pp)))>1/10.0**12:
        mm+=1
        if mm%len(pp)==1:
            pass
        s=min(1,1/sum(abss(u)))
        cnt=0
        while dot(u, grad(add(t,mult(s,u)),pp),pp)>0 and s*sum(abss(u))<len(u):
            s*=2
            cnt+=1
        a=0
        b=s
        beg=a
        end=b
        A=dot(u, grad(add(t,mult(a,u)),pp),pp)
        B=dot(u, grad(add(t,mult(b,u)),pp),pp)
        k=0
        while k<20 and abs(A-B)>(1/10.0**12)*max(abs(A),abs(B)):
            mid=(beg+end)/2
            if dot(u, grad(add(t,mult(mid,u)),pp),pp)>0:
                beg=mid
            else:
                end=mid
            
            c=max(beg-(1/10.0**12),min(end+(1/10.0**12),b+(B/(A-B))*(b-a)))
            C=dot(u, grad(add(t,mult(c,u)),pp),pp)
            if abs(a-c)>abs(b-c) and abs(b-c)>0:
                a=b
                A=B
                b=c
                B=C
            else:
                b=a
                B=A
                a=c
                A=C
            if C>0:
                beg=max(beg,c)
            else:
                end=min(end,c)
            k+=1
                
        s=c
            
        oldgrad=grad(t,pp)
        t=add(t,mult(s,u))
        newgrad=grad(t,pp)
        uold=mult(1,u)
        u=mult(1,newgrad)
        if mm%len(pp)!=1:
            u=add(u,mult(dot(newgrad, add(newgrad,mult(-1,oldgrad)),pp)/dot(oldgrad,oldgrad,pp),uold))

    
    ss=sum(abss(grad(t,pp)))
    tt=t[:kk]
    tt.append(0)
    t=tt+t[kk:]
    if ss>1/10.0**12:
        x=str(input("Failed"))
    return t

df['New_feature'] = df.groupby('Class_ID', group_keys=False)['feature'].apply(f)
df

Я сделал что-то не так? Заранее спасибо.

Изменить Вот пример фрейма данных:

df = pd.read_fwf(io.StringIO("""Class_ID  Date           Student_ID      feature  
1         1/1/2023       3               0.02167131     
1         1/1/2023       4               0.17349148     
1         1/1/2023       6               0.08438952     
1         1/1/2023       8               0.04143787     
1         1/1/2023       9               0.02589056
1         1/1/2023       1               0.03866752     
1         1/1/2023       10              0.0461553                                   
3         17/4/2022      5               0.2     
3         17/4/2022      2               0.1     
3         17/4/2022      3               0.55     
3         17/4/2022      4               0.15
7         12/2/2019      3               0.1
7         12/2/2019      5               0.1
7         12/2/2019      12              0.05
7         12/2/2019      8               0.45
7         12/2/2019      6               0.3""")) 

и желаемый результат:

df_outcome = pd.read_fwf(io.StringIO("""Class_ID   Date          Student_ID      feature        New_feature
1         1/1/2023       3               0.02167131     2.385963956274992
1         1/1/2023       4               0.17349148     0
1         1/1/2023       6               0.08438952     1.6510552553095719
1         1/1/2023       8               0.04143787     2.054792417419151
1         1/1/2023       9               0.02589056     2.298129663961289
1         1/1/2023       1               0.03866752     2.0916706205231286
1         1/1/2023       10              0.0461553       1.9965409929949391
3         17/4/2022      5               0.2            0.7980479577400461
3         17/4/2022      2               0.1            1.2532153405902076
3         17/4/2022      3               0.55           0
3         17/4/2022      4               0.15           0.9944188436386611
7         12/2/2019      3               0.1            1.07079092
7         12/2/2019      5               0.1            1.07079092
7         12/2/2019      12              0.05           1.46861021
7         12/2/2019      8               0.45           0
7         12/2/2019      6               0.3            0.32415155"""))

можешь показать, что такое f?

iBeMeltin 09.08.2024 19:34

@iBeMeltin Привет, определение f немного сложное и слишком длинное, чтобы публиковать здесь. По сути, он принимает на вход список любой длины n, а затем выводит другой список длины. И я хотел бы спросить, есть ли способ обойти эту проблему и создать новый столбец.

Nayr borcherds 09.08.2024 19:51

Я не могу ответить на ваш вопрос, поскольку вы не предоставили воспроизводимый пример ошибки.

iBeMeltin 09.08.2024 19:57

@iBelMeltin Привет, я только что отредактировал свой вопрос и включил определение функции f, большое спасибо.

Nayr borcherds 09.08.2024 20:05

пожалуйста, обращайтесь к этому, когда задаете вопросы: stackoverflow.com/help/minimal-reproducible-example

iBeMeltin 09.08.2024 20:21

@iBeMeltin Я обновил вопрос, и теперь доступен минимальный воспроизводимый пример, спасибо.

Nayr borcherds 10.08.2024 07:16

@Nayrborcherds Ваша функция f совершенно нечитабельна. Он демонстрирует некоторые очень плохие привычки в разработке программного обеспечения. Пожалуйста, сначала выполните рефакторинг части кода, чтобы каждая функция имела не более 25 строк (основной принцип).

Luke L 12.08.2024 01:02
Почему в 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
7
131
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Метод создания pp неправильный. Судя по вашему коду, pp — это нан.

Я исправил метод f ниже:

def f(ppp):
    kk = 0
    maxx = ppp.iloc[0]
    print(f"maxx is {maxx}")
    print(f"ppp is {ppp}")
    for k in range(len(ppp)):
        if ppp.iloc[k] > maxx:
            kk = k
            maxx = ppp.iloc[k]
    pp = pd.concat([ppp.iloc[:kk], ppp.iloc[kk + 1 :]]).reset_index(drop=True)
    print(f"pp is {pp}")
    t = []
    for k in range(len(pp)):
        t.append(math.sqrt(2 * math.log(1 / pp.iloc[k])))

    u = grad(t, pp)
    mm = 0
    while mm <= 50 * len(pp) and sum(abss(grad(t, pp))) > 1 / 10.0**12:
        mm += 1
        if mm % len(pp) == 1:
            pass
        s = min(1, 1 / sum(abss(u)))
        cnt = 0
        while dot(u, grad(add(t, mult(s, u)), pp), pp) > 0 and s * sum(abss(u)) < len(
            u
        ):
            s *= 2
            cnt += 1
        a = 0
        b = s
        beg = a
        end = b
        A = dot(u, grad(add(t, mult(a, u)), pp), pp)
        B = dot(u, grad(add(t, mult(b, u)), pp), pp)
        k = 0
        while k < 20 and abs(A - B) > (1 / 10.0**12) * max(abs(A), abs(B)):
            mid = (beg + end) / 2
            if dot(u, grad(add(t, mult(mid, u)), pp), pp) > 0:
                beg = mid
            else:
                end = mid

            c = max(
                beg - (1 / 10.0**12),
                min(end + (1 / 10.0**12), b + (B / (A - B)) * (b - a)),
            )
            C = dot(u, grad(add(t, mult(c, u)), pp), pp)
            if abs(a - c) > abs(b - c) and abs(b - c) > 0:
                a = b
                A = B
                b = c
                B = C
            else:
                b = a
                B = A
                a = c
                A = C
            if C > 0:
                beg = max(beg, c)
            else:
                end = min(end, c)
            k += 1

        s = c

        oldgrad = grad(t, pp)
        t = add(t, mult(s, u))
        newgrad = grad(t, pp)
        uold = mult(1, u)
        u = mult(1, newgrad)
        if mm % len(pp) != 1:
            u = add(
                u,
                mult(
                    dot(newgrad, add(newgrad, mult(-1, oldgrad)), pp)
                    / dot(oldgrad, oldgrad, pp),
                    uold,
                ),
            )

    ss = sum(abss(grad(t, pp)))
    tt = t[:kk]
    tt.append(0)
    t = tt + t[kk:]
    if ss > 1 / 10.0**12:
        x = str(input("Failed"))
    return t


На самом деле, возможно, это часть функции, но ее можно запустить, чтобы получить результат с помощью предоставленного вами MRE. Возможно, дополнительная ошибка была вызвана использованием панд.

большое спасибо за вашу помощь. Я попытался запустить код и получил следующее: Class_ID Дата Student_ID Feature New_feature 0 1 1/1/2023 3 0.021671 NaN 1 1 1/1/2023 4 0.173491 [2.385963956274992, 0, 1.6510552553095719, 2.0... 2 1 1/ 1/2023 6 0,084390 NaN 3 1 1/1/2023 8 0,041438 [0,7980479577400461, 1,2532153405902076, 0, 0.... 4 1 1/1/2023 9 0,025891 NaN 5 1 /1/2023 1 0,038668 NaN 6 1 1 /1/2023 10 0,046155 NaN 7 3 17.04.2022 5 0,200000 NaN 8 3 17.04.2022 2 0,100000 NaN 9 3 17.04.2022 3 0,550000 NaN 10 3 17.04.2022 4 50000 NaN список сосредоточено в 1 ячейке для каждой расы

Nayr borcherds 12.08.2024 09:20

Привет, кажется, произошла ошибка в столбце объекта. Можете ли вы предоставить некоторые данные объекта? Просто поддельные данные — это нормально.

lif cc 12.08.2024 11:02

Дорогой @lif cc, я только что добавил некоторые данные, пожалуйста, посмотрите редактирование образца ввода данных и желаемого результата, большое спасибо.

Nayr borcherds 12.08.2024 12:07

Извините, только что обнаружил ошибку в фрейме данных, только что обновился и теперь не должен содержать ошибок.

Nayr borcherds 13.08.2024 08:18

Я исправил это сейчас, мне не следует использовать .apply, а вместо этого следует использовать .transform. Большое спасибо за вашу помощь!

Nayr borcherds 13.08.2024 18:07

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