Как улучшить скорость определенных подпрограмм? - PullRequest
0 голосов
/ 04 октября 2019

Я пытаюсь работать с некоторыми базовыми актуарными математиками в Python.

У меня есть база данных, состоящая из 1000+ человек и их информация о пенсии.

В этой задаче яработаю с этими переменными: m_age: возраст застрахованного лица в месяцах m_tmpness: временная выгода, если временная. m_tmbenef: время, прошедшее в месяцах с начала выплаты. m_интерес: процентная ставка для выгоды. tableid: идентификационный номер для актуарной таблицы. mytable_n: qx (вероятность смерти до конца возраста x) из актуарной таблицы. У меня есть несколько таблиц, так что это mytable_1, mytable_2, ... mytable_n

In[2]: m_age
Out[2]: [877, 877, 797, 797, 794]

In[3]: m_tmpness
Out[3]: [240, 240, 0, 120, 120]

In[4]: m_tmbenef
Out[4]: [101, 28, 0, 118, 118]

In[5]: m_interest
Out[5]: [0.0016515813019202241,
 0.0016515813019202241,
 0.0023039138595752906,
 0.0040741237836483535,
 0.0040741237836483535]

In[6]: mytable_1
Out[6]:
0       0.000337
1       0.000337
2       0.000337
...
1500    1.000000
Name: at49m, Length: 1501, dtype: float64

Я рассчитал значения lx (количество людей, живущих в возрасте x) для каждой таблицы, чтобы поддержать вычисление Nx и Dx. Я должен рассчитать Dx и Nx для каждого человека в моей базе данных, в соответствии с его данными. Dx - это просто lx * 1 / (1 + интерес) ^ x. Nx - сумма всех значений Dx из определенной точки. Если x = 0, Nx = D0 + D1 + D2 + ... + Dn. Если x = 50, Nx = D50 + D51 + ... + Dn. Абсолютно легко рассчитать Dx для каждого человека, но я борюсь с этим, потому что мне нужны все значения от Dx до определенного возраста для каждого человека, чтобы вычислить их Nx в определенном возрасте.

Итак, вот что яДо сих пор пытался:

import pandas
lx_mytable_1 = [100000 if i==0 else 0 for i in range(len(mytable_1))]
for i in range(len(mytable_1)):
lx_mytable_1[i] = lx_mytable_1[i-1]*(1-mytable_1[i-1])
### Replicate it to n tables

### Dx and Nx
def Dx(x,lx,qx,interest):
    D_x = [((1/(1+interest))**i)*lx[i] for i in range(len(qx))]
    return(D_x[x])

def Nx(x,lx,qx,interest):
    N_x = 0
    for i in range(len(qx)):
        N_x = N_x + Dx(x=i,lx=lx,qx=qx,interest=interest)
    return(N_x)

### And one should run it like this, for example:
### Nx(x=100,lx=lx_mytable_1,qx=mytable_1,interest=m_interest)

aux_NX = [0 for i in range(len(tableid))]
for i in range(len(tableid)):
    if (tableid[i] == 0):
        aux_NX[i] = 0.0
    else:
        if (tableid[i] == 1):
            aux_NX[i] = Nx(x=PBCIDADE[i],lx=lx_mytable_1,qx=mytable_1,interest=m_interest[i])
        else:
            if (tableid[i] == 2):
                aux_NX[i] = Nx(x=PBCIDADE[i],lx=lx_mytable_2,qx=mytable_2,interest=m_interest[i])
            else:
                if (tableid[i] == 3):
                    aux_NX[i] = Nx(x=PBCIDADE[i],lx=lx_mytable_3,qx=mytable_3,interest=m_interest[i])
                else:
                    if (tableid[i] == 4):
                        aux_NX[i] = Nx(x=PBCIDADE[i],lx=lx_mytable_4,qx=mytable_4,interest=m_interest[i])
                    else:
                        if (tableid[i] == 5):
                            aux_NX[i] = Nx(x=PBCIDADE[i],lx=lx_mytable_5,qx=mytable_5,interest=m_interest[i])
                        ### And as many elses and ifs as necessary... Currently I'm using 15 tables.

Когда я запускаю его для одной строки, это нормально. Но когда я запускаю его для 1000+ строк, это может занять несколько часов, чтобы работать правильно. Вероятно, это потому, что я вызываю цикл for в Nx, а Dx использует другой цикл for с 1500 итерациями в Dx и Nx ...

Мой вопрос: существует ли вычислительно более быстрый способ сделатьтакой же? Как?

1 Ответ

0 голосов
/ 04 октября 2019

Я рекомендую провести некоторое тестирование с модулем timeit .

Затем вы можете точно узнать, какие части вашего кода выполняются долго, а какие - быстро. Затем вы можете использовать эти знания, чтобы задать более конкретный вопрос о том, как оптимизировать ваш код.

Для быстрого сканирования вашего кода, я бы порекомендовал использовать словарь для хранения ваших lx_mytable_2 таблиц. Затем вы можете просто ссылаться на них как lx_mytable[i] и использовать тот же индекс в существующем цикле for, а не 10 if else операторов. Это сделает ваш код намного чище, и вам не придется писать новую строку кода по мере роста ваших данных.

В качестве примечания попробуйте использовать синтаксис elif вместо else: if: в отдельных строках.

...