<filename>case_sharkit_final.py
# -*- coding: utf-8 -*-
"""case_SharkIT_final.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1wTvpkUmGDpBei7EvTtyFgCUkpcAwhBlA
"""

# instalar as dependências
!apt-get install openjdk-8-jdk-headless -qq > /dev/null
!wget -q https://archive.apache.org/dist/spark/spark-2.4.4/spark-2.4.4-bin-hadoop2.7.tgz
!tar xf spark-2.4.4-bin-hadoop2.7.tgz
!pip install -q findspark

# configurar as variáveis de ambiente
import os
os.environ["JAVA_HOME"] = "/usr/lib/jvm/java-8-openjdk-amd64"
os.environ["SPARK_HOME"] = "/content/spark-2.4.4-bin-hadoop2.7"

# tornar o pyspark "importável"
import findspark
findspark.init('spark-2.4.4-bin-hadoop2.7')


# iniciar uma sessão local e importar dados do Airbnb
from pyspark.sql import SparkSession
sc = SparkSession.builder.master('local[*]').getOrCreate()

from pyspark.sql import *
from pyspark.sql.types import *                      
from pyspark.sql import functions
from pyspark.sql.functions import col
from pyspark.sql.functions import substring
from pyspark.sql.functions import explode

# download do http para arquivo local
!wget --quiet --show-progress https://noverde-data-engineering-test.s3.amazonaws.com/loans_sample.csv

# carregando dados do arquivo Csv
df_loans = sc.read.csv("./loans_sample.csv", inferSchema=True, header=True)

# ver algumas informações sobre os tipos de dados de cada coluna
df_loans.printSchema()
df_loans.show()

# download do http para arquivo local
!wget --quiet --show-progress https://noverde-data-engineering-test.s3.amazonaws.com/installments_sample.json

Spark_DF_Json = (sc.read.option("multiline", "true").option("inferSchema", "true").json('./installments_sample.json')                 )
# data = Spark_DF_Json.select("data").collect()[0]['data']
# Spark_DF_Json.printSchema()
# Spark_DF_Json.show()

from pyspark.sql.functions import to_date
data_json = Spark_DF_Json.select(explode('data'))
data_json.printSchema()
installments_df = data_json.select(col('col.loan_id'),col('col.number').alias('installment_number'),col('col.due_date').alias('due_date'))
installments_df = installments_df.withColumn("due_date", to_date(substring('due_date', 0, 10), "yyyy-MM-dd"))
installments_df.show()

# download do http para arquivo local
!wget --quiet --show-progress https://noverde-data-engineering-test.s3.amazonaws.com/payments_sample.parquet
df_spark_parquet = sc.read.format("parquet").load("./payments_sample.parquet")
df_spark_parquet.printSchema()
df_payment = df_spark_parquet.select(col('loan_id'),col('payment_id').alias('id'), col('payment_date'),col('payment_method').alias('method'),\
                                     col('paid_amount').alias('amount'))
df_payment.show()

# faço aqui o join de 3 dataframes, desse jeito o spark entende que 'loan_id' é uma coluna em comum para os 3 e cria apenas uma em df_concat
df_concat = df_loans.join(installments_df, ["loan_id"]).join(df_payment, ["loan_id"])
df_concat.show()

df = df_concat.toPandas()
df

# verifico se existem valores nulos na coluna de pagamantos
df.payment_date.isnull().sum()

df.loc [df ['payment_date'] <= df ['due_date'], 'latency'] = 'False'
df.loc [df ['payment_date'] > df ['due_date'], 'latency'] = 'True'
df

import numpy as np
from datetime import datetime

df.loc[:,'Diference_pay_day'] = (df['payment_date'].sub(df['due_date']))/np.timedelta64(1, 'D')

# se o pagamento esta atrasado há mais de 30 dias o valor e 'True' - significa q a dívida está em aberto
# se o atraso for maior  q 30 dias , mas o pagamento foi efetuado = 'False'

df.loc [df ['Diference_pay_day'] >= 30 & df['payment_date'].isnull(), 'Over30'] = 'True'
df.loc [df ['Diference_pay_day'] >= 30 & df['payment_date'].notnull(), 'Over30'] = 'False'
df

df.columns

"""Salvo a Table em um arquivo parquet"""

# descarto aqui a coluna auxiliar 'Diference_pay_day' e salvo a table no arquivo parquet

df.drop('Diference_pay_day', axis=1, inplace=True)
df.to_parquet('loan_documents.parquet')

"""Leio o arquivo parquet, transformo em um dataframe spark e dou início às respostas para as 4 perguntas"""

df_loan_documents = sc.read.format('parquet').load('loan_documents.parquet')
df_loan_documents.show()

df_vencimento_2019 = df_loan_documents.filter(df_loan_documents['due_date'].between('2019-01-01', '2019-12-31'))
df_faturamento_2019 = df_loan_documents.filter(df_loan_documents['payment_date'].between('2019-01-01', '2019-12-31'))
# df_vencimento_2019.show()
type(df_faturamento_2019)

from pyspark.sql.functions import lit
# import org.apache.spark.sql.functions.typedLit
df_venc = df_vencimento_2019.sort('due_date').groupBy("due_date").sum().select(col('sum(amount)').alias('venc_amount')).withColumn('year', lit('2019')).toPandas()
df_venc

df_fat = df_faturamento_2019.sort('payment_date').groupBy("payment_date").sum()\
.filter(df_faturamento_2019.payment_date != '2019-05-15').filter(df_faturamento_2019.payment_date != '2019-06-11')\
            .select('payment_date',col('sum(amount)').alias('amount')).toPandas()
df_fat

import pandas as pd
p1 = pd.concat([df_fat,df_venc], axis=1) 
p1.loc[:,'Ratio'] = (round(p1['amount']/ (p1['venc_amount'])*100))
# p1 = p1[['year','amount', 'Ratio']]
# p1.loc['payment_date'] = p1.payment_date.astype(str)[4:7]

"""Resposta pergunta 1"""

datas = list(p1.payment_date.values)
month = []
for data in datas[:8]:
  # if data != 'NaN':
  month.append(data.strftime('%m'))
meses = pd.DataFrame(month, columns=['month'])
meses

P1 =pd.concat([p1,meses], axis = 1)
P1 = P1[['month', 'year', 'amount', 'Ratio']]
P1

df_payday = df_spark_mens_2019.select('payday', 'accepted_at').toPandas()
df_payday.payday.mode()

df_spark_mens_2019 = df_loan_documents.filter(df_loan_documents['accepted_at'].between('2019-01-01', '2019-12-31'))

df_means_pd = df_spark_mens_2019.sort('accepted_at').groupBy("accepted_at").mean()\
.select(col('accepted_at').alias('Date'),col('avg(period)').alias('avg_period'),col('avg(interest_rate)').alias('avg_interest_ratio'),\
        col('avg(payday)').alias('freq_payday')).withColumn('year', lit('2019'))\
        .withColumn("date", to_date(substring('Date', 0, 10), "yyyy-MM-dd"))\
        .toPandas()

df_means_pd

"""Resposta 2"""

# df_means_pd.Date = df_means_pd.Date
datas = list(df_means_pd.date.values)
month = []
for data in datas:
  # if data != 'NaN':
  month.append(data.strftime('%m'))


meses = pd.DataFrame(month, columns=['month'])
meses

P2 = pd.concat([df_means_pd, meses], axis = 1)
P2 = P2[['month', 'year', 'avg_period',	'avg_interest_ratio',	'avg_payday']]
P2

df_loan_documents.groupby('period').count().show()
df_loan_documents.groupby('interest_rate').count().show()

"""Identificando a taxa média de juros para tal período"""

avg_interest_rate_6 = df_loan_documents.filter(df_loan_documents['period'] == '6').groupby('interest_rate').mean().select(col('avg(interest_rate)').alias('avg_interest_rate')).toPandas()
avg_interest_rate_9 = df_loan_documents.filter(df_loan_documents['period'] == '9').groupby('interest_rate').mean().select(col('avg(interest_rate)').alias('avg_interest_rate')).toPandas()
avg_interest_rate_12 = df_loan_documents.filter(df_loan_documents['period'] == '12').groupby('interest_rate').mean().select(col('avg(interest_rate)').alias('avg_interest_rate')).toPandas()

"""Identificando o dia mais frequente de pagamento para tal periodo"""

freq_payday_6 = df_loan_documents.filter(df_loan_documents['period'] == '6').groupby('payday').count().toPandas()
freq_payday_9 = df_loan_documents.filter(df_loan_documents['period'] == '9').groupby('payday').count().toPandas()
freq_payday_12 = df_loan_documents.filter(df_loan_documents['period'] == '12').groupby('payday').count().toPandas()

# o dia 25 é o que aparece mais vezes para period = 12  - moda
freq_payday_12.max()

# o dia 25 é o que aparece mais vezes para period = 9  - moda
freq_payday_9.max()

# o dia 25 é o que aparece mais vezes para period = 6  - moda
freq_payday_6.max()

"""Resposta 3"""



interest_rate_6 = df_loan_documents.filter(df_loan_documents['period'] == '6').groupby('interest_rate').count().withColumn('period', lit('6')).withColumn('freq_payday', lit('25')).toPandas()
interest_rate_9 = df_loan_documents.filter(df_loan_documents['period'] == '9').groupby('interest_rate').count().withColumn('period', lit('9')).withColumn('freq_payday', lit('25')).toPandas()
interest_rate_12 = df_loan_documents.filter(df_loan_documents['period'] == '12').groupby('interest_rate').count().withColumn('period', lit('12')).withColumn('freq_payday', lit('25')).toPandas()


df_p6= pd.concat([interest_rate_6, avg_interest_rate_6], axis=1)
df_p9= pd.concat([interest_rate_9, avg_interest_rate_9], axis=1)
df_p12= pd.concat([interest_rate_12, avg_interest_rate_12], axis=1)


p3 = pd.concat([df_p6,df_p9,df_p12])
p3 = p3[['period', 'interest_rate', 'count', 'avg_interest_rate', 'freq_payday']]
p3.columns = ['period', 'interest_ratio', 'count_loan_id', 'avg_interest_rate', 'freq_payday']
p3

df_loan_documents.show()

df_total_portfolio = df_loan_documents.groupby('loan_id').count().select('loan_id',col('count').alias('total_portfolio')).toPandas()
df_total_portfolio

"""Quando 'Over30' é false não há atraso maior ou igual a 30 dias para tal contrato

Over30 = True implica débito em aberto
"""

df_matured = df_loan_documents.filter(df_loan_documents['Over30'] == 'False').groupby('loan_id').count().select('loan_id', col('count').alias('matured_portfolio') ).toPandas()

df_over30 = df_loan_documents.filter(df_loan_documents['Over30'] == 'True').groupby('loan_id').count().select('loan_id', col('count').alias('over30_true') ).toPandas()

df_matured

"""Resposta 4

O motivo pelo qual os campos de 'ratio' são em maioria nulos se justifica:

Não existem contratos com atraso maior ou igual a 30 dias para essas linhas.
"""

# df_total_portfolio.join(df_matured, ["loan_id"]).join((df_over30, ["loan_id"]))

p4 = pd.concat([df_total_portfolio,df_matured,df_over30], axis=1)
# p4.dropna(subset=['total_portfolio'], inplace=True)
p4 = p4[['total_portfolio','matured_portfolio', 'over30_true']]
# p4.loc[:,'ratio'] = p4.over30_true/p4.total_portfolio * 100

p4.loc [p4 ['over30_true'].notnull(), 'ratio'] = p4.over30_true/p4.total_portfolio * 100
p4


<filename>case_sharkit_final.py
# -*- coding: utf-8 -*-
"""case_SharkIT_final.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1wTvpkUmGDpBei7EvTtyFgCUkpcAwhBlA
"""

# instalar as dependências
!apt-get install openjdk-8-jdk-headless -qq > /dev/null
!wget -q https://archive.apache.org/dist/spark/spark-2.4.4/spark-2.4.4-bin-hadoop2.7.tgz
!tar xf spark-2.4.4-bin-hadoop2.7.tgz
!pip install -q findspark

# configurar as variáveis de ambiente
import os
os.environ["JAVA_HOME"] = "/usr/lib/jvm/java-8-openjdk-amd64"
os.environ["SPARK_HOME"] = "/content/spark-2.4.4-bin-hadoop2.7"

# tornar o pyspark "importável"
import findspark
findspark.init('spark-2.4.4-bin-hadoop2.7')


# iniciar uma sessão local e importar dados do Airbnb
from pyspark.sql import SparkSession
sc = SparkSession.builder.master('local[*]').getOrCreate()

from pyspark.sql import *
from pyspark.sql.types import *                      
from pyspark.sql import functions
from pyspark.sql.functions import col
from pyspark.sql.functions import substring
from pyspark.sql.functions import explode

# download do http para arquivo local
!wget --quiet --show-progress https://noverde-data-engineering-test.s3.amazonaws.com/loans_sample.csv

# carregando dados do arquivo Csv
df_loans = sc.read.csv("./loans_sample.csv", inferSchema=True, header=True)

# ver algumas informações sobre os tipos de dados de cada coluna
df_loans.printSchema()
df_loans.show()

# download do http para arquivo local
!wget --quiet --show-progress https://noverde-data-engineering-test.s3.amazonaws.com/installments_sample.json

Spark_DF_Json = (sc.read.option("multiline", "true").option("inferSchema", "true").json('./installments_sample.json')                 )
# data = Spark_DF_Json.select("data").collect()[0]['data']
# Spark_DF_Json.printSchema()
# Spark_DF_Json.show()

from pyspark.sql.functions import to_date
data_json = Spark_DF_Json.select(explode('data'))
data_json.printSchema()
installments_df = data_json.select(col('col.loan_id'),col('col.number').alias('installment_number'),col('col.due_date').alias('due_date'))
installments_df = installments_df.withColumn("due_date", to_date(substring('due_date', 0, 10), "yyyy-MM-dd"))
installments_df.show()

# download do http para arquivo local
!wget --quiet --show-progress https://noverde-data-engineering-test.s3.amazonaws.com/payments_sample.parquet
df_spark_parquet = sc.read.format("parquet").load("./payments_sample.parquet")
df_spark_parquet.printSchema()
df_payment = df_spark_parquet.select(col('loan_id'),col('payment_id').alias('id'), col('payment_date'),col('payment_method').alias('method'),\
                                     col('paid_amount').alias('amount'))
df_payment.show()

# faço aqui o join de 3 dataframes, desse jeito o spark entende que 'loan_id' é uma coluna em comum para os 3 e cria apenas uma em df_concat
df_concat = df_loans.join(installments_df, ["loan_id"]).join(df_payment, ["loan_id"])
df_concat.show()

df = df_concat.toPandas()
df

# verifico se existem valores nulos na coluna de pagamantos
df.payment_date.isnull().sum()

df.loc [df ['payment_date'] <= df ['due_date'], 'latency'] = 'False'
df.loc [df ['payment_date'] > df ['due_date'], 'latency'] = 'True'
df

import numpy as np
from datetime import datetime

df.loc[:,'Diference_pay_day'] = (df['payment_date'].sub(df['due_date']))/np.timedelta64(1, 'D')

# se o pagamento esta atrasado há mais de 30 dias o valor e 'True' - significa q a dívida está em aberto
# se o atraso for maior  q 30 dias , mas o pagamento foi efetuado = 'False'

df.loc [df ['Diference_pay_day'] >= 30 & df['payment_date'].isnull(), 'Over30'] = 'True'
df.loc [df ['Diference_pay_day'] >= 30 & df['payment_date'].notnull(), 'Over30'] = 'False'
df

df.columns

"""Salvo a Table em um arquivo parquet"""

# descarto aqui a coluna auxiliar 'Diference_pay_day' e salvo a table no arquivo parquet

df.drop('Diference_pay_day', axis=1, inplace=True)
df.to_parquet('loan_documents.parquet')

"""Leio o arquivo parquet, transformo em um dataframe spark e dou início às respostas para as 4 perguntas"""

df_loan_documents = sc.read.format('parquet').load('loan_documents.parquet')
df_loan_documents.show()

df_vencimento_2019 = df_loan_documents.filter(df_loan_documents['due_date'].between('2019-01-01', '2019-12-31'))
df_faturamento_2019 = df_loan_documents.filter(df_loan_documents['payment_date'].between('2019-01-01', '2019-12-31'))
# df_vencimento_2019.show()
type(df_faturamento_2019)

from pyspark.sql.functions import lit
# import org.apache.spark.sql.functions.typedLit
df_venc = df_vencimento_2019.sort('due_date').groupBy("due_date").sum().select(col('sum(amount)').alias('venc_amount')).withColumn('year', lit('2019')).toPandas()
df_venc

df_fat = df_faturamento_2019.sort('payment_date').groupBy("payment_date").sum()\
.filter(df_faturamento_2019.payment_date != '2019-05-15').filter(df_faturamento_2019.payment_date != '2019-06-11')\
            .select('payment_date',col('sum(amount)').alias('amount')).toPandas()
df_fat

import pandas as pd
p1 = pd.concat([df_fat,df_venc], axis=1) 
p1.loc[:,'Ratio'] = (round(p1['amount']/ (p1['venc_amount'])*100))
# p1 = p1[['year','amount', 'Ratio']]
# p1.loc['payment_date'] = p1.payment_date.astype(str)[4:7]

"""Resposta pergunta 1"""

datas = list(p1.payment_date.values)
month = []
for data in datas[:8]:
  # if data != 'NaN':
  month.append(data.strftime('%m'))
meses = pd.DataFrame(month, columns=['month'])
meses

P1 =pd.concat([p1,meses], axis = 1)
P1 = P1[['month', 'year', 'amount', 'Ratio']]
P1

df_payday = df_spark_mens_2019.select('payday', 'accepted_at').toPandas()
df_payday.payday.mode()

df_spark_mens_2019 = df_loan_documents.filter(df_loan_documents['accepted_at'].between('2019-01-01', '2019-12-31'))

df_means_pd = df_spark_mens_2019.sort('accepted_at').groupBy("accepted_at").mean()\
.select(col('accepted_at').alias('Date'),col('avg(period)').alias('avg_period'),col('avg(interest_rate)').alias('avg_interest_ratio'),\
        col('avg(payday)').alias('freq_payday')).withColumn('year', lit('2019'))\
        .withColumn("date", to_date(substring('Date', 0, 10), "yyyy-MM-dd"))\
        .toPandas()

df_means_pd

"""Resposta 2"""

# df_means_pd.Date = df_means_pd.Date
datas = list(df_means_pd.date.values)
month = []
for data in datas:
  # if data != 'NaN':
  month.append(data.strftime('%m'))


meses = pd.DataFrame(month, columns=['month'])
meses

P2 = pd.concat([df_means_pd, meses], axis = 1)
P2 = P2[['month', 'year', 'avg_period',	'avg_interest_ratio',	'avg_payday']]
P2

df_loan_documents.groupby('period').count().show()
df_loan_documents.groupby('interest_rate').count().show()

"""Identificando a taxa média de juros para tal período"""

avg_interest_rate_6 = df_loan_documents.filter(df_loan_documents['period'] == '6').groupby('interest_rate').mean().select(col('avg(interest_rate)').alias('avg_interest_rate')).toPandas()
avg_interest_rate_9 = df_loan_documents.filter(df_loan_documents['period'] == '9').groupby('interest_rate').mean().select(col('avg(interest_rate)').alias('avg_interest_rate')).toPandas()
avg_interest_rate_12 = df_loan_documents.filter(df_loan_documents['period'] == '12').groupby('interest_rate').mean().select(col('avg(interest_rate)').alias('avg_interest_rate')).toPandas()

"""Identificando o dia mais frequente de pagamento para tal periodo"""

freq_payday_6 = df_loan_documents.filter(df_loan_documents['period'] == '6').groupby('payday').count().toPandas()
freq_payday_9 = df_loan_documents.filter(df_loan_documents['period'] == '9').groupby('payday').count().toPandas()
freq_payday_12 = df_loan_documents.filter(df_loan_documents['period'] == '12').groupby('payday').count().toPandas()

# o dia 25 é o que aparece mais vezes para period = 12  - moda
freq_payday_12.max()

# o dia 25 é o que aparece mais vezes para period = 9  - moda
freq_payday_9.max()

# o dia 25 é o que aparece mais vezes para period = 6  - moda
freq_payday_6.max()

"""Resposta 3"""



interest_rate_6 = df_loan_documents.filter(df_loan_documents['period'] == '6').groupby('interest_rate').count().withColumn('period', lit('6')).withColumn('freq_payday', lit('25')).toPandas()
interest_rate_9 = df_loan_documents.filter(df_loan_documents['period'] == '9').groupby('interest_rate').count().withColumn('period', lit('9')).withColumn('freq_payday', lit('25')).toPandas()
interest_rate_12 = df_loan_documents.filter(df_loan_documents['period'] == '12').groupby('interest_rate').count().withColumn('period', lit('12')).withColumn('freq_payday', lit('25')).toPandas()


df_p6= pd.concat([interest_rate_6, avg_interest_rate_6], axis=1)
df_p9= pd.concat([interest_rate_9, avg_interest_rate_9], axis=1)
df_p12= pd.concat([interest_rate_12, avg_interest_rate_12], axis=1)


p3 = pd.concat([df_p6,df_p9,df_p12])
p3 = p3[['period', 'interest_rate', 'count', 'avg_interest_rate', 'freq_payday']]
p3.columns = ['period', 'interest_ratio', 'count_loan_id', 'avg_interest_rate', 'freq_payday']
p3

df_loan_documents.show()

df_total_portfolio = df_loan_documents.groupby('loan_id').count().select('loan_id',col('count').alias('total_portfolio')).toPandas()
df_total_portfolio

"""Quando 'Over30' é false não há atraso maior ou igual a 30 dias para tal contrato

Over30 = True implica débito em aberto
"""

df_matured = df_loan_documents.filter(df_loan_documents['Over30'] == 'False').groupby('loan_id').count().select('loan_id', col('count').alias('matured_portfolio') ).toPandas()

df_over30 = df_loan_documents.filter(df_loan_documents['Over30'] == 'True').groupby('loan_id').count().select('loan_id', col('count').alias('over30_true') ).toPandas()

df_matured

"""Resposta 4

O motivo pelo qual os campos de 'ratio' são em maioria nulos se justifica:

Não existem contratos com atraso maior ou igual a 30 dias para essas linhas.
"""

# df_total_portfolio.join(df_matured, ["loan_id"]).join((df_over30, ["loan_id"]))

p4 = pd.concat([df_total_portfolio,df_matured,df_over30], axis=1)
# p4.dropna(subset=['total_portfolio'], inplace=True)
p4 = p4[['total_portfolio','matured_portfolio', 'over30_true']]
# p4.loc[:,'ratio'] = p4.over30_true/p4.total_portfolio * 100

p4.loc [p4 ['over30_true'].notnull(), 'ratio'] = p4.over30_true/p4.total_portfolio * 100
p4


# -*- coding: utf-8 -*- case_SharkIT_final.ipynb  Automatically generated by Colaboratory.  Original file is located at     https://colab.research.google.com/drive/1wTvpkUmGDpBei7EvTtyFgCUkpcAwhBlA # instalar as dependências # configurar as variáveis de ambiente # tornar o pyspark "importável" # iniciar uma sessão local e importar dados do Airbnb # download do http para arquivo local # carregando dados do arquivo Csv # ver algumas informações sobre os tipos de dados de cada coluna # download do http para arquivo local # data = Spark_DF_Json.select("data").collect()[0]['data'] # Spark_DF_Json.printSchema() # Spark_DF_Json.show() # download do http para arquivo local # faço aqui o join de 3 dataframes, desse jeito o spark entende que 'loan_id' é uma coluna em comum para os 3 e cria apenas uma em df_concat # verifico se existem valores nulos na coluna de pagamantos # se o pagamento esta atrasado há mais de 30 dias o valor e 'True' - significa q a dívida está em aberto # se o atraso for maior  q 30 dias , mas o pagamento foi efetuado = 'False' Salvo a Table em um arquivo parquet # descarto aqui a coluna auxiliar 'Diference_pay_day' e salvo a table no arquivo parquet Leio o arquivo parquet, transformo em um dataframe spark e dou início às respostas para as 4 perguntas # df_vencimento_2019.show() # import org.apache.spark.sql.functions.typedLit # p1 = p1[['year','amount', 'Ratio']] # p1.loc['payment_date'] = p1.payment_date.astype(str)[4:7] Resposta pergunta 1 # if data != 'NaN': Resposta 2 # df_means_pd.Date = df_means_pd.Date # if data != 'NaN': Identificando a taxa média de juros para tal período Identificando o dia mais frequente de pagamento para tal periodo # o dia 25 é o que aparece mais vezes para period = 12  - moda # o dia 25 é o que aparece mais vezes para period = 9  - moda # o dia 25 é o que aparece mais vezes para period = 6  - moda Resposta 3 Quando 'Over30' é false não há atraso maior ou igual a 30 dias para tal contrato  Over30 = True implica débito em aberto Resposta 4  O motivo pelo qual os campos de 'ratio' são em maioria nulos se justifica:  Não existem contratos com atraso maior ou igual a 30 dias para essas linhas. # df_total_portfolio.join(df_matured, ["loan_id"]).join((df_over30, ["loan_id"])) # p4.dropna(subset=['total_portfolio'], inplace=True) # p4.loc[:,'ratio'] = p4.over30_true/p4.total_portfolio * 100