USER
he creado este código python para importar tablas biométricas generacionales (calculando la lambda para poder generarlas) y no generacionales, además de calcular a partir de las mismas parámetros como lx, dx, ex, etc...
import pandas as pd
class BiometricTableImporter:
def __init__(self, file_path):
self.file_path = file_path
def import_table(self, sheet_name, usecols, skiprows, nrows, lambda_col=None):
df = pd.read_excel(
self.file_path,
sheet_name=sheet_name,
usecols=usecols,
skiprows=skiprows,
nrows=nrows,
header=None
)
if lambda_col is not None:
# Extraer los valores de lambda y asignarlos a una nueva columna en el DataFrame
lambda_values = df.iloc[:, lambda_col]
df["lambda"] = lambda_values
# Si deseas, puedes eliminar la columna original de lambda para evitar confusiones
# df.drop(df.columns[lambda_col], axis=1, inplace=True)
return df
if __name__ == "__main__":
file_path = r"F:\1Assegurances\MUTUALITATS\MANUAL\2 NORMATIVA\5.-Taules actuarials\3bis.-Anexos Resolución de 17 de diciembre de 2020.xlsx"
importer = BiometricTableImporter(file_path)
# Parámetros para la primera tabla
sheet_name1 = "Anexo 2.1"
usecols1 = "C: E"
skiprows1 = 8
nrows1 = 121
PERF2020_COL_1 = importer.import_table(sheet_name1, usecols1, skiprows1, nrows1, lambda_col=2)
# Parámetros para la segunda tabla
sheet_name2 = "Anexo 2.1"
usecols2 = "G: I"
skiprows2 = 8
nrows2 = 121
PERM2020_COL_1 = importer.import_table(sheet_name2, usecols2, skiprows2, nrows2, lambda_col=2)
# Parámetros para la tercera tabla
sheet_name3 = "Anexo 2.1"
usecols3 = "M: O"
skiprows3 = 8
nrows3 = 121
PERF2020_IND_1 = importer.import_table(sheet_name3, usecols3, skiprows3, nrows3, lambda_col=2)
# Parámetros para la cuarta tabla
sheet_name4= "Anexo 2.1"
usecols4 = "Q: S"
skiprows4 = 8
nrows4 = 121
PERM2020_IND_1 = importer.import_table(sheet_name4, usecols4, skiprows4, nrows4, lambda_col=2)
# Parámetros para la quinta tabla
sheet_name5 = "Anexo 1.1"
usecols5 = "C: D"
skiprows5 = 8
nrows5 = 121
PERF2020_COL_2 = importer.import_table(sheet_name5, usecols5, skiprows5, nrows5, lambda_col=1)
# Parámetros para la sexta tabla
sheet_name6 = "Anexo 1.1"
usecols6 = "E: F"
skiprows6 = 8
nrows6 = 121
PERM2020_COL_2 = importer.import_table(sheet_name6, usecols6, skiprows6, nrows6, lambda_col=1)
# Parámetros para la séptima tabla
sheet_name7 = "Anexo 1.1"
usecols7 = "H: I"
skiprows7 = 8
nrows7 = 121
PERF2020_IND_2 = importer.import_table(sheet_name7, usecols7, skiprows7, nrows7, lambda_col=1)
# Parámetros para la octava tabla
sheet_name8 = "Anexo 1.1"
usecols8 = "J: K"
skiprows8 = 8
nrows8 = 121
PERM2020_IND_2 = importer.import_table(sheet_name8, usecols8, skiprows8, nrows8, lambda_col=1)
# Parámetros para la novena tabla
sheet_name9 = "Anexo 1.2 y Anexo 1.3"
usecols9 = "B: B"
skiprows9 = 8
nrows9 = 121
PASEF2020_GEN_2 = importer.import_table(sheet_name9, usecols9, skiprows9, nrows9)
# Parámetros para la décima tabla
sheet_name10 = "Anexo 1.2 y Anexo 1.3"
usecols10 = "C: C"
skiprows10 = 8
nrows10 = 121
PASEM2020_GEN_2 = importer.import_table(sheet_name10, usecols10, skiprows10, nrows10)
# Parámetros para la undécima tabla
sheet_name11 = "Anexo 1.2 y Anexo 1.3"
usecols11 = "E: E"
skiprows11 = 8
nrows11 = 121
PASEF2020_DEC_2 = importer.import_table(sheet_name11, usecols11, skiprows11, nrows11)
# Parámetros para la duodécima tabla
sheet_name12 = "Anexo 1.2 y Anexo 1.3"
usecols12 = "F: F"
skiprows12 = 8
nrows12 = 121
PASEM2020_DEC_2 = importer.import_table(sheet_name12, usecols12, skiprows12, nrows12)
# Parámetros para la décimo tercera tabla
sheet_name13 = "Anexo 2.2,Anexo 2.3 y Anexo 2.4"
usecols13 = "B: B"
skiprows13 = 8
nrows13 = 121
PASEF_REL_1 = importer.import_table(sheet_name13, usecols13, skiprows13, nrows13)
# Parámetros para la décimo cuarta tabla
sheet_name14 = "Anexo 2.2,Anexo 2.3 y Anexo 2.4"
usecols14 = "C: C"
skiprows14 = 9
nrows14 = 121
PASEM_REL_1 = importer.import_table(sheet_name14, usecols14, skiprows14, nrows14)
# Parámetros para la décimo quinta quinta tabla
sheet_name15 = "Anexo 2.2,Anexo 2.3 y Anexo 2.4"
usecols15 = "E: E"
skiprows15 = 9
nrows15 = 121
PASEF_NOREL_1 = importer.import_table(sheet_name15, usecols15, skiprows15, nrows15)
# Parámetros para la décimo sexta tabla
sheet_name16 = "Anexo 2.2,Anexo 2.3 y Anexo 2.4"
usecols16 = "F: F"
skiprows16 = 9
nrows16 = 121
PASEM_NOREL_1 = importer.import_table(sheet_name16, usecols16, skiprows16, nrows16)
# Parámetros para la décimo séptima tabla
sheet_name17 = "Anexo 2.2,Anexo 2.3 y Anexo 2.4"
usecols17 = "H: H"
skiprows17 = 9
nrows17 = 121
PASEF_DEC_1 = importer.import_table(sheet_name17, usecols17, skiprows17, nrows17)
# Parámetros para la décimo octava tabla
sheet_name18 = "Anexo 2.2,Anexo 2.3 y Anexo 2.4"
usecols18 = "I: I"
skiprows18 = 9
nrows18 = 121
PASEM_DEC_1 = importer.import_table(sheet_name18, usecols18, skiprows18, nrows18)
# Puedes continuar creando instancias para importar más tablas según sea necesario…
# Y luego hacer algo con las tablas, como imprimir o procesarlas
print(PERM2020_COL_1)
print(PERF2020_COL_1)
print(PERM2020_IND_1)
print(PERF2020_IND_1)
print(PERM2020_COL_2)
print(PERF2020_COL_2)
print(PERM2020_IND_2)
print(PERF2020_IND_2)
print(PASEM_DEC_1)
print(PASEF_DEC_1)
print(PASEM2020_DEC_2)
print(PASEF2020_DEC_2)
print(PASEM_REL_1)
print(PASEF_REL_1)
print(PASEM_NOREL_1)
print(PASEF_NOREL_1)
# Imprime los nombres de las columnas de PERF2020_COL_1
print(PERF2020_COL_1.columns)
print(PASEM_DEC_1.columns)
#import pdb; pdb.set_trace()#para parar la ejecución del código
# SEGUNDO-----> GENERAMOS TODAS LAS VARIABLES CON UNA TABLA DE LAS ANTERIORES
import numpy as np
import pandas as pd
class ActuarialTable:
def __init__(self, qx_base: pd.Series, lambda_values: pd.Series = None,
birth_year: int = None, base_year: int = None,
interest_rate: float = 0.03, l0: int = 100000):
self.qx_base = qx_base / 1000 # qx_base should be in ‘per thousand’ unit
self.is_generational = lambda_values is not None and birth_year is not None and base_year is not None
self.interest_rate = interest_rate
self.l0 = l0
if self.is_generational:
# Adjust based on birth year if it’s a generational table
self.lambda_values = lambda_values
self.birth_year = birth_year
self.base_year = base_year
self.qx = self.adjust_qx_by_birth_year()
else:
# Otherwise, use the base probabilities
self.qx = self.qx_base
self.lx = [self.l0]
self.i = interest_rate # Tasa de interés anual efectiva
self.l0 = l0 # Población inicial de lx
self.lx = [l0] # Se inicializa con la población al inicio
self.dx = [0.0] * len(self.qx)
self.ex = [0.0] * len(self.qx)
self.Dx = [0.0] * len(self.qx)
self.Nx = [0.0] * len(self.qx)
self.Cx = [0.0] * len(self.qx)
self.Mx = [0.0] * len(self.qx)
self.nEx = [0.0] * len(self.qx)
# Llama al método que realiza los cálculos.
self._calculate_actuarial_variables()
def adjust_qx_by_birth_year(self):
return self.qx_base * np.exp(-self.lambda_values * (self.birth_year + self.qx_base.index - self.base_year))
def _calculate_actuarial_variables(self):
n = len(self.qx)
# Calcular lx y dx
for x in range(1, n + 1):
lx_previous = self.lx[x - 1]
dx = lx_previous * self.qx[x - 1]
self.dx[x - 1] = dx
lx = lx_previous - dx
self.lx.append(lx)
# Calcular ex (expectativa de vida) para cada edad x
self.ex[-1] = 0 # Última expectativa de vida es 0
for x in reversed(range(n - 1)):
lx_sum = sum(self.lx[x + 1:])
if self.lx[x]>0:
self.ex[x] = lx_sum / self.lx[x]
else:
self.ex[x]=np.nan
# Calcular Dx y Nx
for x in range(n):
if self.lx[x] > 0:
self.Dx[x] = self.lx[x] / ((1 + self.i) ** x)
for x in range(n):
self.Nx[x] = sum(self.Dx[x:])
# Calcular Cx y Mx
for x in range(n - 1):
self.Cx[x] = self.dx[x] / ((1 + self.i) ** (x + 0.5))
for x in range(n):
self.Mx[x] = sum(self.Cx[x:])
# Calcular nEx
for x in range(n - 1):
if self.Dx[x] > 0:
self.nEx[x] = self.Nx[x + 1] / self.Dx[x]
# La última edad w es inicialmente desconocida, se calculará como 0 si lx es 0
self.w = n + self.lx[n:].index(0) if 0 in self.lx[n:] else n
# Suponiendo que ‘PERF2020_COL_1’ tiene los datos qx relevantes
generational_qx = PERF2020_COL_1[2] # en verde el título de la columna de las qx
non_generational_qx = PASEF_NOREL_1[4] # en verde el título de la columna de las qx
# También debes definir las demás variables antes de intentar crear instancias de ‘ActuarialTable’
# Por ejemplo:
lambda_values = None # O tu valor real de lambda_values
birth_year = None # O tu valor real de birth_year
base_year = None # O tu valor real de base_year
# Luego de que todas las variables requeridas estén definidas correctamente, puedes crear las instancias
non_generational_actuarial_table = ActuarialTable(qx_base=non_generational_qx)
# Y para una tabla generacional, asegúrate de tener los valores correctos en las variables antes de intentar esto
generational_actuarial_table = ActuarialTable(qx_base=generational_qx, lambda_values=lambda_values,
birth_year=birth_year, base_year=base_year)
# Create an instance for a non-generational table
non_generational_actuarial_table = ActuarialTable(non_generational_qx)
# Create an instance for a generational table (with birth year adjustment)
generational_actuarial_table = ActuarialTable(generational_qx, lambda_values, birth_year, base_year)
ahora necesitaria codificar alguna manera para poder extraer los datos de esas tablas, por ejemplo, si quiero extrar el valor de qx de la tabla generacional PERM2020_COL_1 con año de nacimiento 1950 para una persona de 60 añosASSISTANT
Para extraer el valor de \(qx\) de una tabla generacional como `PERM2020_COL_1` con un año de nacimiento específico, por ejemplo, 1950, para una persona de 60 años, primero necesitas asegurarte de que tu clase `ActuarialTable` pueda manejar adecuadamente este tipo de solicitud y luego proporcionar una interfaz para obtener el valor de \(qx\).
Para lograr esto, puedes agregar un método en tu clase `ActuarialTable` para obtener el valor de \(qx\) ajustado por una edad específica. Este método puede hacer uso de `adjust_qx_by_birth_year` si la tabla es generacional, es decir, si se han proporcionado `lambda_values`, `birth_year` y `base_year`. A continuación, se muestra cómo se podría modificar la clase para incluir dicho método:
```python
class ActuarialTable:
def __init__(self, qx_base: pd.Series, lambda_values: pd.Series = None,
birth_year: int = None, base_year: int = None,
interest_rate: float = 0.03, l0: int = 100000):
# El resto del código de inicialización permanece igual
# Métodos ya existentes como adjust_qx_by_birth_year, _calculate_actuarial_variables, etc.
def get_qx(self, age: int, birth_year: int = None):
"""
Obtener el valor qx para una edad específica y, opcionalmente, año de nacimiento
para tablas generacionales.
"""
if self.is_generational and birth_year:
# Ajusta para el año de nacimiento si se proporciona.
# Asume que self.qx ya está ajustada por el año de nacimiento proporcionado en __init__.
# Si desea usar un año de nacimiento diferente al de la inicialización, necesitarás ajustar nuevamente.
adjusted_qx_val = np.exp(-self.lambda_values.loc[age] * (birth_year + age - self.base_year)) * self.qx_base.loc[age]
return adjusted_qx_val
else:
# Retorna el valor qx base para tablas no generacionales o generacionales sin reajuste.
return self.qx_base.loc[age]
```
Luego, para utilizar esta funcionalidad, necesitarías asegurarte de que las instancias de `ActuarialTable` se inicialicen con toda la información necesaria, incluidos los valores de lambda (si es aplicable), y utilizar el método `get_qx` para obtener los valores de \(qx\) para edades específicas:
```python
# Asegúrate de que generational_qx, lambda_values, birth_year y base_year están correctamente definidos.
# Aquí 'generational_qx' debe ser una serie pandas con el índice correcto representando la edad.
lambda_values_for_PERM2020_COL_1 = None # Definir este valor según tus datos
birth_year = 1950
base_year_for_PERM2020_COL_1 = None # Definir este valor según tus datos
generational_table_PERM2020_COL_1 = ActuarialTable(qx_base=generational_qx, lambda_values=lambda_values_for_PERM2020_COL_1,
birth_year=birth_year, base_year=base_year_for_PERM2020_COL_1)
age = 60 # Edad para la cual quieres obtener qx
qx_value_at_age_60_for_birth_year_1950 = generational_table_PERM2020_COL_1.get_qx(age, birth_year=birth_year)
print(f"El valor qx para una persona nacida en {birth_year}, a la edad de {age} años, es {qx_value_at_age_60_for_birth_year_1950}")
```
Recuerda definir o ajustar el `lambda_values_for_PERM2020_COL_1` y el `base_year_for_PERM2020_COL_1` según tus datos específicos, ya que en tu código inicial se pasan como `None` que básicamente indica que no se están utilizando aún. Estos valores son cruciales para calcular el ajuste por generación correctamente.