<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
  <title>Artigos de Marcos H. Silva</title>
  <link>https://www.marcosmhs.com.br/</link>
  <atom:link href="https://www.marcosmhs.com.br/feed.xml" rel="self" type="application/rss+xml"/>
  <description>Artigos sobre dados, data science, tecnologia e liderança, por Marcos H. Silva.</description>
  <language>pt-BR</language>
  <lastBuildDate>Fri, 16 Oct 2026 13:56:26 GMT</lastBuildDate>
  <item>
    <title>De 1 ano para 3 dias: como reinventamos a estratégia de Data na Rentcars</title>
    <link>https://www.marcosmhs.com.br/artigos/como-reinventamos-estrategia-de-dados-na-rentcars/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/como-reinventamos-estrategia-de-dados-na-rentcars/</guid>
    <pubDate>Tue, 25 Aug 2026 17:32:40 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>AI</category>
    <category>DataViz</category>
    <description>Um dos primeiros desafios que recebi quando cheguei na Rentcars foi migrar 134 dashboards de uma ferramenta de BI de mercado para o Metabase. Estimativa? Um…</description>
    <content:encoded><![CDATA[<p>Um dos primeiros desafios que recebi quando cheguei na Rentcars foi migrar 134 dashboards de uma ferramenta de BI de mercado para o Metabase. Estimativa? Um ano de trabalho para pouco mais de 10 dashboards.</p>
<p>Regras complexas, necessidade de converter indicadores de uma ferramenta de mercado para uma solução open source.</p>
<p>No meio do caminho, tomamos uma decisão mais ousada. Em vez de simplesmente trocar uma ferramenta por outra, abandonamos a abordagem tradicional e construímos algo sob medida: um portal de dashboards baseado em HTML, servido direto do Athena (nosso Data Lake), sem servidor de aplicação no meio.</p>
<p>O resultado? A migração levou 3 dias — não um ano.</p>
<p>Um pouco da solução que criamos:</p>
<p>→ Dashboards em HTML puro, com gráficos SVG renderizados no próprio navegador — sem depender de licenças ou infraestrutura pesada de BI.</p>
<p>→ O pulo do gato: usamos DuckDB direto no browser, executando SQL sobre arquivos Parquet. Na prática, o dashboard replica a interatividade completa (filtros, cruzamentos, drill-down) de uma ferramenta de BI tradicional — só que rodando na máquina de quem acessa.</p>
<p>→ Separação rígida entre dado e apresentação, orquestração via Airflow, deploy em ECS/Fargate e controle de acesso via SSO.</p>
<p>E aqui está o ponto que mais importa: a maior parte desse trabalho foi feita com apoio de IA. Foi ela que acelerou a geração de código, a replicação dos dashboards e a documentação.</p>
<p>Mas — e esse &quot;mas&quot; é fundamental — nada disso teria funcionado sem o expertise do time. Foi o conhecimento prático dos engenheiros que garantiu a qualidade, definiu a arquitetura, validou cada métrica e, de quebra, permitiu que aproveitássemos a migração para eliminar dashboards obsoletos ou incorretos que ninguém tinha coragem de mexer.</p>
<p>Hoje temos uma solução extremamente robusta que fornece indicadores corporativos para toda a empresa de forma estável, escalável e de fácil manutenção (também tocada de forma acelerada com IA)</p>
<p>Se eu puder deixar uma mensagem que pode gerar algum impacto positivo no seu trabalho é:</p>
<p>IA sem conhecimento prático é como dar um robô cirurgião para um macaco: até pode operar, mas nada de bom vai sair dali.</p>
<p>A ferramenta amplifica quem sabe o que está fazendo. Ela não substitui o saber</p>
]]></content:encoded>
  </item>
  <item>
    <title>Você sabe como seu time realmente te vê?</title>
    <link>https://www.marcosmhs.com.br/artigos/voce-sabe-como-seu-time-realmente-te-ve/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/voce-sabe-como-seu-time-realmente-te-ve/</guid>
    <pubDate>Fri, 29 Aug 2025 19:40:27 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>Liderança</category>
    <category>Desenvolvimento</category>
    <description>A jornada de um líder é, em sua essência, uma jornada de autoconhecimento. Quanto melhor nos entendemos – como agimos, como somos percebidos e o impacto que…</description>
    <content:encoded><![CDATA[<p>Olá,</p>
<p>A jornada de um líder é, em sua essência, uma jornada de autoconhecimento. Quanto melhor nos entendemos – como agimos, como somos percebidos e o impacto que causamos – mais eficazes nos tornamos em guiar, inspirar e desenvolver nossas equipes.</p>
<p>No entanto, existe uma lacuna fundamental que todos nós possuímos: a diferença entre quem achamos que somos e como as outras pessoas realmente nos veem. É nesta lacuna que moram os maiores desafios e as mais ricas oportunidades de crescimento.</p>
<p>Para explorar esse espaço, existe um modelo psicológico brilhante e atemporal criado nos anos 50 por Joseph Luft e Harrington Ingham: a <strong>Janela de Johari</strong>.</p>
<p><strong>A Janela de Johari</strong></p>
<p>Imagine uma janela dividida em quatro painéis (áreas). Cada painel representa uma faceta da nossa personalidade e da nossa relação com os outros:</p>
<p><strong>1. Área Aberta:</strong> Este é o painel da transparência. Contém as características que você conhece sobre si mesmo e que os outros também conhecem. Quanto maior esta área, mais eficaz é a comunicação, a confiança e a colaboração no time. Um líder com uma &quot;Arena&quot; grande tende a ser visto como autêntico e direto.</p>
<p><strong>2.Área Cega:</strong> Aqui está o ouro do desenvolvimento! Este painel contém o que os outros veem em você, mas que você não percebe. Podem ser manias, reações, pontos fortes subestimados ou pontos fracos que impactam a equipe sem que você saiba. Descobrir seus pontos cegos é um presente, embora exija coragem para recebê-lo.</p>
<p><strong>3. Área Oculta:</strong> Esta área guarda o que você sabe sobre si, mas escolhe não revelar aos outros por medo, insegurança ou desejo de manter certa imagem. Embora todos tenhamos direito à nossa privacidade, uma &quot;Fachada&quot; muito grande pode gerar desconfiança e criar barreiras na comunicação.</p>
<p><strong>4. Área Desconhecida:</strong> O quadrante do potencial inexplorado. Representa as características e habilidades que nem você, nem os outros, conhecem ainda. Essa área pode ser descoberta através de novos desafios, experiências e, claro, do processo de dar e receber feedback.</p>
<p><strong>O Poder da Dinâmica em Equipe</strong></p>
<p>O objetivo ao usar a Janela de Johari não é expor ninguém, mas sim <strong>aumentar a área do &quot;Eu Aberto&quot;</strong> para todo o time, começando pelo líder.</p>
<p>Quando um líder se dispõe a explorar seus &quot;Pontos Cegos&quot;, ele sinaliza para toda a equipe que a vulnerabilidade é uma força e que o desenvolvimento é um valor inegociável. Isso cria um ciclo virtuoso de confiança e segurança psicológica, onde a comunicação flui de forma mais honesta e construtiva.</p>
<p><strong>Como colocar em prática de forma segura?</strong></p>
<p>Tradicionalmente, a dinâmica da Janela de Johari é feita com post-its e conversas em grupo. No entanto, para que as pessoas se sintam seguras para apontar &quot;pontos cegos&quot; de uma liderança, o anonimato pode ser um catalisador poderoso.</p>
<p>Foi pensando em facilitar esse processo e garantir a segurança psicológica necessária que eu desenvolvi uma versão online e gratuita da dinâmica. A ferramenta permite que cada um faça sua autoavaliação e convide os colegas para contribuírem de forma anônima, organizando as respostas automaticamente nos quatro quadrantes.</p>
<p>Para explorar minha própria Janela de Johari eu criei o site <strong><a href="https://teb-janelajohari.web.app/?trk=article-ssr-frontend-pulse_little-text-block" target="_blank" rel="noopener">https://teb-janelajohari.web.app/</a></strong> para que eu e meu time pudéssemos realizar esta dinâmica mesmo estando em locais separados. Ela é gratuita e permite feedbacks 100% anônimos de forma clara e que lhe ajudarão no seu desenvolvimento.</p>
<p>Em tempos de IA, ao final é oferecido um prompt que pode ser utilizado no Chat GPT, Google Gemini ou qualquer outra ferramenta que você desejar :)</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-Jzb6D07BugHcx%2Fcontent%2F3a716d9fedfc1cfe.png?alt=media&amp;token=5d010e1f-f3e1-48a9-8b2b-2dec9b7ef511" alt="" loading="lazy" decoding="async">
<p>O verdadeiro crescimento na liderança não vem de ter todas as respostas, mas de ter a coragem de fazer as perguntas certas sobre nós mesmos.</p>
<p>Você já conhecia a Janela de Johari? Qual dos quatro quadrantes você acredita que tem mais potencial de transformação na sua carreira? Vamos conversar nos comentários!</p>
<p>#Autoconhecimento #Liderança #DesenvolvimentoPessoal #JanelaDeJohari #InteligenciaEmocional #ComunicaçãoEficaz #Psicologia #GestãoDePessoas #CulturaOrganizacional</p>
]]></content:encoded>
  </item>
  <item>
    <title>A new approach for creating multilevel models</title>
    <link>https://www.marcosmhs.com.br/artigos/a-new-approach-for-creating-multilevel-models/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/a-new-approach-for-creating-multilevel-models/</guid>
    <pubDate>Tue, 25 Jul 2023 12:01:59 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>RStudio</category>
    <category>Modelagem Multinível</category>
    <description>I believe that multilevel models or generalized linear models are one of the best tools for predicting continuous values, given their adaptability and…</description>
    <content:encoded><![CDATA[<figure><img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-gQwCB6A5FmdDA%2Fcontent%2F8607f41b5e5b0e46.jpg?alt=media&amp;token=6290d3cf-84f4-44c2-b4b5-0f652ab8a950" alt="Photo by Pierre Bamin on Unsplash" loading="lazy" decoding="async"><figcaption>Photo by Pierre Bamin on Unsplash</figcaption></figure>
<p>I believe that multilevel models or generalized linear models are one of the best tools for predicting continuous values, given their adaptability and explanatory capacity. However, like other machine learning methods, they also pose a challenge when you need to define which variables should be used to achieve the best results.</p>
<p>A common strategy for refining multilevel models is the step-up approach, a method proposed by Raudenbush and Bryk in a 2002 article. This technique involves an iterative process where variables are gradually added to the model based on statistical criteria, such as the p-value and a regression coefficient like the log-likelihood, Bayesian Information Criterion (BIC), or Akaike Information Criterion (AIC).</p>
<p>In the step-up strategy, an initial null model is created without predictor variables to assess the statistical significance of random intercept effects. Then, the model is enriched with other variables, and this step is repeated until the final model or complete model is created. I covered this topic in an article I wrote for the conclusion of an MBA last year, and the PDF can be accessed through <a href="https://1drv.ms/b/s!AtsEI2mTf0TYruoBIGWA4IiXvIlJnw?e=TDW3TP" target="_blank" rel="noopener">this link</a> (in portuguese).</p>
<p>Considering a way to ensure the best possible result for a model, I followed a slightly different approach, creating a refinement method aimed at achieving the best model regardless of the step-up strategy.</p>
<p>This approach aims to test all possible combinations of level 1 and level 2 variables to find the best possible indicators, which are:</p>
<ul>
<li><strong>Log-likelihood</strong>: a widely used method for model comparison in the academic field.</li>
<li><strong>BIC</strong> (Bayesian Information Criterion): a method that builds upon the Log-likelihood but applies a penalty based on the number of parameters in the model. Therefore, more complex models need to show a better improvement compared to models with fewer parameters.</li>
<li><strong>RMSE</strong> (Root Mean Squared Error): a measure that compares predicted values with actual values and prevents positive and negative deviations from canceling each other out. Taking advantage of the deterministic nature of regression models, where results are predictable, this indicator can be calculated while evaluating the model using the same training dataset for testing.</li>
</ul>
<p>Below, I present a practical example of this strategy.</p>
<p>This method was created with the help of Python, using the “MixedLM” method from the “statsmodels” package, and it follows some naming conventions used by the package and others that complement its execution:</p>
<ul>
<li><strong>y_variable</strong>: the name of the response variable, which will be generated by the model.</li>
<li><strong>formula_variables</strong>: a list of higher-level variables.</li>
<li><strong>groups</strong>: the variable used as a grouping factor.</li>
<li><strong>re_formula_variables</strong>: a list of lower-level variables.</li>
<li><strong>data</strong>: a DataFrame containing the data for model creation.</li>
<li><strong>detailed_verbose</strong> (default False): indicates whether all tested combinations will be displayed during execution (True) or only the final result (False).</li>
<li><strong>show_best_model_summary</strong> (default True): indicates whether the summary of the model will be displayed at the end of execution according to the “summary()” method.</li>
<li><strong>class_criterion</strong> (default ‘llk’): indicates the model’s classification criterion, which can be ‘llk’ for Log-likelihood, ‘bic’ for Bayesian Information Criterion, or ‘RMSE’ for Root Mean Squared Error.</li>
<li><strong>icc_test</strong> (default False): indicates whether the intraclass correlation coefficient value should be displayed, which is used to assess the percentage of data impacted by grouping at different levels.</li>
<li><strong>hlm_model_check</strong> (default False): indicates whether the p-value of the model should be displayed. This information helps identify whether the null model is statistically significant at a 95% confidence level. This way, it is possible to check the significance of the random term and determine if traditional models such as Ordinary Least Squares (OLS) are suitable for this scenario (Tabachnick and Fidell, 2013).</li>
</ul>
<p>Considering the fictitious dataset:</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-gQwCB6A5FmdDA%2Fcontent%2F1e003deebb30639f.png?alt=media&amp;token=96fec6bc-a072-4f52-b869-1d3d196cc6b8" alt="" loading="lazy" decoding="async">
<p>Given the dataset provided:</p>
<ul>
<li><strong>loja</strong>: Store identifier</li>
<li><strong>cidade</strong>: City identifier</li>
<li><strong>receita</strong>: Accumulated revenue in 12 months</li>
<li><strong>nps</strong>: Net Promoter Score in 12 months</li>
<li>tempo_medio_contrato: Average contract duration of the sales team</li>
<li><strong>perc_fidelidade</strong>: Percentage of loyalty club customers who made a purchase in this store in 12 months</li>
<li><strong>inflação</strong>: City’s inflation percentage in 12 months</li>
<li><strong>desemprego</strong>: City’s unemployment rate in 12 months</li>
<li><strong>pib</strong>: City’s Gross Domestic Product (GDP) in 12 months</li>
</ul>
<p>It is possible to observe that the variables can be separated into 2 levels:</p>
<ul>
<li><strong>Level 1</strong> — Store: receita, nps, tempo_medio_contrato, and perc_fidelidade</li>
<li><strong>Level 2</strong> — City: inflação, desemprego, and pib</li>
</ul>
<p>With this in mind, the execution of all possible combinations for evaluating random intercepts and slopes in a multilevel model would be as follows:</p>
<pre class="code"><code class="hljs">hlm2_refined = <span class="hljs-title function_">hlm2_model_test</span>(
    y_variable = <span class="hljs-string">&#x27;receita&#x27;</span>, 
    formula_variables = [<span class="hljs-string">&#x27;desemprego&#x27;</span>, <span class="hljs-string">&#x27;inflacao&#x27;</span>, <span class="hljs-string">&#x27;pib&#x27;</span>],
    groups = <span class="hljs-string">&#x27;cidade&#x27;</span>, 
    re_formula_variables = [<span class="hljs-string">&#x27;nps&#x27;</span>, <span class="hljs-string">&#x27;tempo_medio_contrato&#x27;</span>, <span class="hljs-string">&#x27;perc_fidelidade&#x27;</span>],
    data = df_sells,
    class_criterion = <span class="hljs-string">&#x27;llk&#x27;</span>)</code></pre>
<p>Note that level 1 variables (store) are listed in the re_formula_variables property, while level 2 variables (city) are listed in the re_formula property. In this case, we will have 49 combinations [(3 + 3 + 1) * (3 + 3 + 1)], and here are some examples:</p>
<ul>
<li>Formula = receita ~ desemprego and re_formula = nps</li>
<li>Formula = receita ~ desemprego and re_formula = nps + tempo_medio_contrato</li>
<li>Formula = receita ~ desemprego + inflacao and re_formula = nps</li>
</ul>
<p>Each combination will generate and evaluate a model, and in the end, they will be ranked according to the chosen criterion, in this case, log-likelihood. After ranking, the results of the process will be displayed, divided into two parts:</p>
<p>Best model: A summary of the model and classification criterion result.</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-gQwCB6A5FmdDA%2Fcontent%2F1c34222548e3db99.png?alt=media&amp;token=d90732e9-db33-4b92-b44b-e23f517379ad" alt="" loading="lazy" decoding="async">
<p>Summary: with the summary of the selected model using the MixedLM method.</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-gQwCB6A5FmdDA%2Fcontent%2F60c1f6ee9fdc5df1.png?alt=media&amp;token=ccfaf67c-6119-4dcc-a59d-22bda7dd5262" alt="" loading="lazy" decoding="async">
<p>To create a model that considers the influence of city-level variables on the stores, it is necessary to modify the method call, now considering these effects, as shown in the example below:</p>
<pre class="code"><code class="hljs">hlm2_final = <span class="hljs-title function_">hlm2_model_test</span>(
    y_variable = <span class="hljs-string">&#x27;receita&#x27;</span>, 
    formula_variables = [<span class="hljs-string">&#x27;desemprego&#x27;</span>, <span class="hljs-string">&#x27;inflacao&#x27;</span> ,
                         <span class="hljs-string">&#x27;nps&#x27;</span>, <span class="hljs-string">&#x27;tempo_medio_contrato&#x27;</span>,
                         <span class="hljs-string">&#x27;nps:desemprego&#x27;</span>, <span class="hljs-string">&#x27;nps:inflacao&#x27;</span>,
                         <span class="hljs-string">&#x27;tempo_medio_contrato:desemprego&#x27;</span>, <span class="hljs-string">&#x27;tempo_medio_contrato:inflacao&#x27;</span>],
    groups = <span class="hljs-string">&#x27;cidade&#x27;</span>, 
    re_formula_variables = [<span class="hljs-string">&#x27;nps&#x27;</span>, <span class="hljs-string">&#x27;tempo_medio_contrato&#x27;</span>],
    data = df_sells,
    class_criterion = <span class="hljs-string">&#x27;llk&#x27;</span>)</code></pre>
<p>In this case, there will be 765 or [(8 + 28 + 56 + 70 + 56 + 28 + 8 + 1) * (2 + 1)] model combinations to be evaluated, and this process will take a little longer, depending on the computer where it is being executed. In the end, we will have the result, separated in the same way as in the previous example:</p>
<p>Best Model</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-gQwCB6A5FmdDA%2Fcontent%2F7df01e822ec4c353.png?alt=media&amp;token=1e75ab23-cafc-4ed7-8b9e-5ff0b47e635d" alt="" loading="lazy" decoding="async">
<p>Summary</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-gQwCB6A5FmdDA%2Fcontent%2Fd7b5e46c20e9acea.png?alt=media&amp;token=de0f8a91-99c7-413c-a8b1-d081efe602ae" alt="" loading="lazy" decoding="async">
<p>Please note that this time there are variables that did not show statistical significance at a 95% confidence level. However, the log-likelihood improved compared to the previous model, and the combinations without these variables did not show an improvement in predictive capability, so they were discarded.</p>
<p>Since the return of this method is a DataFrame with all the combinations tested, the indicators, and a copy of the model generated by the MixedLM method, it is possible to evaluate the tests performed and compare them. To obtain the best model, simply execute the command:</p>
<pre class="code"><code class="hljs">hlm2_final_model = hlm2_final.iloc[<span class="hljs-number">0</span>][<span class="hljs-string">&#x27;model&#x27;</span>]</code></pre>
<p>In this example, the variable hlm2_final_model will store the model generated by the MixedLM method. To visualize the top five evaluated models, we can use the head command, as shown in the example below:</p>
<pre class="code"><code class="hljs">hlm2_final.<span class="hljs-title function_">head</span>(<span class="hljs-number">5</span>)</code></pre>
<p>The codes used here and more information about the dataset used can be found on my <a href="https://github.com/marcosmhs/HLM2-Model-Test/" target="_blank" rel="noopener">GitHub</a>.</p>
<p>If you have found any errors or have any suggestions for improvement, please send me a message at <a href="mailto:marcosmhs@live.com">marcosmhs@live.com</a>, and I will be glad to further enhance this text and give you credit.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Como encontrar a melhor estratégia de investimento</title>
    <link>https://www.marcosmhs.com.br/artigos/como-encontrar-a-melhor-estrategia-de-investimento/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/como-encontrar-a-melhor-estrategia-de-investimento/</guid>
    <pubDate>Wed, 28 Dec 2022 02:04:34 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>Python</category>
    <category>Investimentos</category>
    <description>Imagine que você criou uma carteira de investimentos, com ações de empresas que você conhece e acredita que pode gerar bons resultados e estão alinhadas com…</description>
    <content:encoded><![CDATA[<figure><img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F7c4d8a074adee0b1.jpg?alt=media&amp;token=269a0586-ec4b-4f50-8724-bc8f191ce204" alt="Photo by Austin Distel on Unsplash" loading="lazy" decoding="async"><figcaption>Photo by Austin Distel on Unsplash</figcaption></figure>
<p>Imagine que você criou uma carteira de investimentos, com ações de empresas que você conhece e acredita que pode gerar bons resultados e estão alinhadas com seus critérios de ESG e governança. Vamos supor que você selecionou 6 empresas e possui R$ 60.000 para iniciar sua carteira. Se você preparou 6 cheques de R$ 10.000 para enviar para o escritório de cada uma eu tenho 2 más notícias… A primeira é que não é assim que se compra ações e a segunda é que você pode estar fazendo um mal negócio.</p>
<p>Isso porque empresas diferentes possuem rendimentos diferentes e se o objetivo aqui é garantir um bom rendimento é necessário pensar em como maximizar seus lucros.</p>
<p>Foi isso o que pensou <a href="https://pt.wikipedia.org/wiki/William_Forsyth_Sharpe" target="_blank" rel="noopener">Willian Sharpe</a> em 1966 quando criou um índice para ajudar a encontrar o percentual de investimento em cada item de sua carteira afim de maximizar o retorno com o menor risco possível utilizando apenas os dados históricos das ações. Este índice recebeu o nome de Sharpe Ratio!</p>
<p>Bora lá entender como calcular este negócio, usando o Python!</p>
<p>Como sempre vamos preparar nosso ambiente com as bibliotecas necessárias</p>
<pre class="code"><code class="hljs"><span class="hljs-keyword">import</span> yfinance <span class="hljs-keyword">as</span> yf
<span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-keyword">from</span> scipy.optimize <span class="hljs-keyword">import</span> minimize
<span class="hljs-keyword">from</span> pandas_datareader <span class="hljs-keyword">import</span> data <span class="hljs-keyword">as</span> web

<span class="hljs-comment"># definição do período de seleção dos dados históricos das ações analisadas</span>
start date = datetime.datetime(<span class="hljs-number">2022</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>)
end_date = datetime.datetime(<span class="hljs-number">2022</span>,<span class="hljs-number">11</span>,<span class="hljs-number">30</span>)</code></pre>
<p>Em seguida vamos selecionar as 6 ações de nossa carteira fictícia, neste caso:</p>
<ul>
<li><a href="https://www.google.com/finance/quote/GGBR4:BVMF" target="_blank" rel="noopener">Gerdau</a> (GGBR4.SA) — Produtora de aço</li>
<li><a href="https://www.google.com/finance/quote/CPLE6:BVMF" target="_blank" rel="noopener">Copel</a> (CPLE6.SA) — Companhia de fornecimento de energia Paranaense</li>
<li><a href="https://www.google.com/finance/quote/ASAI3:BVMF" target="_blank" rel="noopener">Assaí</a> (ASAI3.SA) — Atacadista</li>
<li><a href="https://www.google.com/finance/quote/ITUB4:BVMF" target="_blank" rel="noopener">Itaú</a> (ITUB4.SA) — Banco</li>
<li><a href="https://www.google.com/finance/quote/NTCO3:BVMF" target="_blank" rel="noopener">Natura</a> (NTCO3.SA) — Produtos de beleza</li>
<li><a href="https://www.google.com/finance/quote/VALE3:BVMF" target="_blank" rel="noopener">Vale</a> (VALE3.SA) — Mineradora</li>
</ul>
<pre class="code"><code class="hljs"># houve uma alteração no retorno <span class="hljs-keyword">do</span> yahoo finance e esta linha é 
# necessária até que o <span class="hljs-title class_">Pandas</span> <span class="hljs-title class_">DataReader</span> seja corrigido.
yf.<span class="hljs-title function_">pdr_override</span>()
#<span class="hljs-title class_">Gerdau</span>
goau = web.<span class="hljs-title function_">get_data_yahoo</span>([<span class="hljs-string">&#x27;GOAU4.SA&#x27;</span>], start = start_date, end=end_date)
#<span class="hljs-title class_">Copel</span>
cple = web.<span class="hljs-title function_">get_data_yahoo</span>([<span class="hljs-string">&#x27;CPLE6.SA&#x27;</span>], start = start_date, end = end_date)
# <span class="hljs-title class_">Assa</span>í
asai = web.<span class="hljs-title function_">get_data_yahoo</span>([<span class="hljs-string">&#x27;ASAI3.SA&#x27;</span>], start = start_date, end = end_date)
#<span class="hljs-title class_">Ita</span>ú
itub = web.<span class="hljs-title function_">get_data_yahoo</span>([<span class="hljs-string">&#x27;ITUB4.SA&#x27;</span>], start = start_date, end = end_date)
#<span class="hljs-title class_">Natura</span>
ntco = web.<span class="hljs-title function_">get_data_yahoo</span>([<span class="hljs-string">&#x27;NTCO3.SA&#x27;</span>], start = start_date, end = end_date)
#<span class="hljs-title class_">Vale</span>
vale = web.<span class="hljs-title function_">get_data_yahoo</span>([<span class="hljs-string">&#x27;VALE3.SA&#x27;</span>], start = start_date, end = end_date)
# lista com os nomes das ações
stocks_names = [<span class="hljs-string">&#x27;Gerdau&#x27;</span>, <span class="hljs-string">&#x27;Copel&#x27;</span>, <span class="hljs-string">&#x27;Assaí&#x27;</span>, <span class="hljs-string">&#x27;Itaú&#x27;</span>, <span class="hljs-string">&#x27;Natura&#x27;</span>, <span class="hljs-string">&#x27;Vale&#x27;</span>]</code></pre>
<p>Vamos utilizar o código abaixo para ter uma noção do desempenho de cada uma:</p>
<pre class="code"><code class="hljs">fig = plt.<span class="hljs-title function_">figure</span>(figsize = (<span class="hljs-number">20</span>,<span class="hljs-number">8</span>))
gs = fig.<span class="hljs-title function_">add_gridspec</span>(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>, wspace = <span class="hljs-number">0</span>)
(ax1, ax2, ax3), (ax4, ax5, ax6) = gs.<span class="hljs-title function_">subplots</span>()

ax1.<span class="hljs-title function_">plot</span>(goau[<span class="hljs-string">&#x27;Close&#x27;</span>])
ax1.<span class="hljs-title function_">set_title</span>(stocks_names[<span class="hljs-number">0</span>])
ax2.<span class="hljs-title function_">plot</span>(cple[<span class="hljs-string">&#x27;Close&#x27;</span>], )
ax2.<span class="hljs-title function_">set_title</span>(stocks_names[<span class="hljs-number">1</span>])
ax3.<span class="hljs-title function_">plot</span>(asai[<span class="hljs-string">&#x27;Close&#x27;</span>], <span class="hljs-string">&#x27;tab:green&#x27;</span>)
ax3.<span class="hljs-title function_">set_title</span>(stocks_names[<span class="hljs-number">2</span>])
ax4.<span class="hljs-title function_">plot</span>(itub[<span class="hljs-string">&#x27;Close&#x27;</span>], <span class="hljs-string">&#x27;tab:red&#x27;</span>)
ax4.<span class="hljs-title function_">set_title</span>(stocks_names[<span class="hljs-number">3</span>])
ax5.<span class="hljs-title function_">plot</span>(ntco[<span class="hljs-string">&#x27;Close&#x27;</span>], <span class="hljs-string">&#x27;tab:blue&#x27;</span>)
ax5.<span class="hljs-title function_">set_title</span>(stocks_names[<span class="hljs-number">4</span>])
ax6.<span class="hljs-title function_">plot</span>(vale[<span class="hljs-string">&#x27;Close&#x27;</span>], <span class="hljs-string">&#x27;tab:gray&#x27;</span>)
ax6.<span class="hljs-title function_">set_title</span>(stocks_names[<span class="hljs-number">5</span>])</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F4fa2d5c274bb34c8.png?alt=media&amp;token=544f7856-3660-4875-b37f-65c197d8bddb" alt="" loading="lazy" decoding="async">
<p>Podemos ver que a Gerdau, Copel e Assaí apresentam padrões de crescimento interessantes, enquanto Natura, Itaú e Vale trazem queda ou crescimento tímido</p>
<p>Como os dados estão separados em 6 <em>dataframes</em> diferentes precisamos uni-los em um só local e nesta união utilizaremos apenas a coluna <em>Close</em>, que armazena o valor do fechamento da ação em um dia</p>
<pre class="code"><code class="hljs"><span class="hljs-comment"># com o concat será feita a união dos dataframes. A opção axis indica que queremos os dados sejam colocados em colunas diferentes ao invés de concatenar as linhas</span>
stocks = pd.concat([
    goau[<span class="hljs-string">&#x27;Close&#x27;</span>], 
    cple[<span class="hljs-string">&#x27;Close&#x27;</span>], 
    asai[<span class="hljs-string">&#x27;Close&#x27;</span>],
    itub[<span class="hljs-string">&#x27;Close&#x27;</span>],
    ntco[<span class="hljs-string">&#x27;Close&#x27;</span>],
    vale[<span class="hljs-string">&#x27;Close&#x27;</span>]
    ],axis= <span class="hljs-number">1</span>)
<span class="hljs-comment"># agora renomeamos as colunas para que tenham o nome de suas respectivas ações</span>
stocks.columns = stocks_names

stocks. Head(<span class="hljs-number">5</span>)</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F65452e82094bd5f7.png?alt=media&amp;token=9c351234-4fbd-453e-8e14-02843d610fc6" alt="" loading="lazy" decoding="async">
<p>Agora vamos preparar os dados para a análise, começando pela criação de uma matriz com o retorno de cada ação por data, seguindo a fórmula:</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F5e53dd14e7131a0b.png?alt=media&amp;token=6c380064-0ea0-424d-9d7a-d34c3e6ec18f" alt="" loading="lazy" decoding="async">
<p>Onde:</p>
<ul>
<li><em>R</em> é o retorno</li>
<li><em>P</em> é o preço</li>
<li><em>P</em>-1 é o preço na data anterior</li>
</ul>
<p>Todos os elementos são subscritos (t), ou seja, todos são em função do tempo.</p>
<pre class="code"><code class="hljs"><span class="hljs-comment"># neste caso o shift faz o LAG do valor, ou seja, pega o valor correspondente ao dia anterior</span>
returns <span class="hljs-operator">=</span> stocks <span class="hljs-operator">/</span> stocks.shift<span class="hljs-punctuation">(</span><span class="hljs-number">1</span><span class="hljs-punctuation">)</span>
<span class="hljs-comment"># vemos que os primeiros valores são inválidos pois não há uma data anterior para o cálculo</span>
returns. Head<span class="hljs-punctuation">(</span><span class="hljs-number">5</span><span class="hljs-punctuation">)</span></code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F311e7cc80e28e62d.png?alt=media&amp;token=f5eefab5-cbcf-4c82-9bd6-ab8d12e996db" alt="" loading="lazy" decoding="async">
<p>Em seguida faremos a padronização dos valores:</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2Fb45dc1e0d74da5be.png?alt=media&amp;token=8b5511ef-ab1c-43b3-921d-df4f40e2e6e1" alt="" loading="lazy" decoding="async">
<p>Mas não se preocupe porque no Python isso é muito fácil:</p>
<pre class="code"><code class="hljs">log_returns = np.<span class="hljs-title function_">log</span>(returns)
log_returns.<span class="hljs-title function_">head</span>(<span class="hljs-number">5</span>)</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F8a83717ddfee0e72.png?alt=media&amp;token=6c825302-07af-47c7-b32d-a11623458c31" alt="" loading="lazy" decoding="async">
<p>Podemos ver que os valores, que antes oscilavam entre R$ 6 (Copel) e R$ 71(Vale), agora oscilam entre -1 e 1</p>
<h2 id="calculando-o-sharpe-ratio">Calculando o Sharpe Ratio</h2>
<p>Como dito anteriormente, este índice considera o retorno de acordo com o risco envolvido, utilizando dados históricos. Abrindo um pouco a caixa do método, temos a fórmula:</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2Fe0b10043e3302ee4.png?alt=media&amp;token=31eeb68f-98f0-488c-9206-c47044586c32" alt="" loading="lazy" decoding="async">
<p>Onde</p>
<ul>
<li>SR é o Sharpe Ratio, o valor que desejamos obter</li>
<li>(w) é o peso de cada ação. Neste caso o valor normalizado de todos os valores de nossa lista, ou seja, ao somar todos os valores teremos 1 como resultado. Esse valor irá ajudar a definir o percentual de nosso investimento em cada ação. Neste exemplo, w1 é Gerdau, w2 é Copel e assim por diante</li>
<li>R(f) é o retorno caso não exista risco, e como veremos mais adiante é um valor desprezado, não precisaremos dele.</li>
<li>Sigma é desvio padrão ou volatilidade</li>
</ul>
<p><em>w</em> é a soma dos pesos dentro de um determinado dia</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F862214a6d9cfa08c.png?alt=media&amp;token=6191739f-cc25-496c-8562-a2c7870e0906" alt="" loading="lazy" decoding="async">
<p><em>R(w)</em> é retorno do investimento: matriz transposta dos pesos multiplicado pelo valor do dia anterior (log)</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F78beb429bfe828bb.png?alt=media&amp;token=d214b870-1c3c-466f-ad52-62d0a808f7bc" alt="" loading="lazy" decoding="async">
<p><em>sigma(w)</em> — risco do investimento é a raiz da matriz transposta de pesos multiplicado pela soma dos pesos</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F7b955f51326a57e7.png?alt=media&amp;token=6377cf55-ca07-4a28-be25-1d3a71a65a2a" alt="" loading="lazy" decoding="async">
<p>Ao final teremos a fórmula que será utilizada:</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2Fb4de5ce023749c39.png?alt=media&amp;token=ebabc26b-a102-48ef-ae42-1cb940722745" alt="" loading="lazy" decoding="async">
<p>Agora sim, vamos ao cálculo do retorno vs volatilidade, neste caso avaliaremos 10.000 portfólios diferentes, gerando peso aleatórios para cada uma das ações</p>
<pre class="code"><code class="hljs">number_of_portfolios = <span class="hljs-number">10000</span>
number_of_stocks = <span class="hljs-built_in">len</span>(stocks.columns)

<span class="hljs-comment"># vamos criar os vetores que serão utilizados e iniciá-los com zero</span>
weights = np.zeros((number_of_portfolios, number_of_stocks))
expected_return = np.zeros(number_of_portfolios)
expected_volatility = np.zeros(number_of_portfolios)
sharpe_ratio = np.zeros(number_of_portfolios)

<span class="hljs-comment"># Como utilizaremos a média dos retornos padronizados (log_returns), </span>
<span class="hljs-comment"># vamos calculá-la agora para evitar processamento excessivo durante o loop</span>
mean_log_returns = log_returns.mean()

<span class="hljs-comment"># utilizaremos a matriz de covariância (grau de interdependência) </span>
<span class="hljs-comment"># entre as ações de nossa base</span>
sigma = log_returns.cov()

<span class="hljs-comment"># vamos correr todo o portfólio, quanto maior o número de </span>
<span class="hljs-comment"># iterações maior a quantidade combinações a serem feitas</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(number_of_portfolios):
    
    <span class="hljs-comment"># (w)</span>
    <span class="hljs-comment"># criar vetor com pesos aleatórios, usado em cada uma das iterações</span>
    w = np.array(np.random.random(number_of_stocks))
    <span class="hljs-comment"># encontra o percentual de cada peso gerado anteriormente</span>
    w = w / np.<span class="hljs-built_in">sum</span>(w)
    
    <span class="hljs-comment"># salva o valor dentro da matriz</span>
    weights[i,:] = w
    
    <span class="hljs-comment"># R(w)</span>
    <span class="hljs-comment"># calcular o log return multiplicando o valor com LAG pelo peso. </span>
    <span class="hljs-comment"># Esta matriz terá apenas uma coluna, com o retorno esperado para </span>
    <span class="hljs-comment"># aquele dia de todas as ações da carteira</span>
    expected_return[i] = np.<span class="hljs-built_in">sum</span>(mean_log_returns * w)

    <span class="hljs-comment"># sigma(w)</span>
    expected_volatility[i] = np.sqrt(
        np.dot(
            w.T,
            np.dot(sigma, w)
        )
    )

    <span class="hljs-comment"># Sharpe ratio, o retorno dividido pela volatilidade</span>
    sharpe_ratio[i] = expected_return[i] / expected_volatility[i]</code></pre>
<p>Uma vez calculado o Sharpe ratio para todos os portfólios vamos verificar o melhor índice, aquele com maior retorno.</p>
<pre class="code"><code class="hljs"><span class="hljs-comment"># retorna a posição que garante o maior retorno nas ações </span>
<span class="hljs-comment"># de acordo com o sharpe ratio</span>
max_index <span class="hljs-operator">=</span> sharpe_ratio.argmax<span class="hljs-punctuation">(</span><span class="hljs-punctuation">)</span>

<span class="hljs-comment"># agora podemos ver qual o percentual de nosso orçamento que </span>
<span class="hljs-comment"># podemos alocar em cada uma das ações para maximizar nosso retorno.</span>
weights<span class="hljs-punctuation">[</span>max_index<span class="hljs-punctuation">,</span> <span class="hljs-operator">:</span><span class="hljs-punctuation">]</span></code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F30bd2e20b6677ac3.png?alt=media&amp;token=56660778-eb8e-4880-88d2-962083cdd41c" alt="" loading="lazy" decoding="async">
<p>Para melhorar a visualização dos dados podemos criar um gráfico de barras, com o código abaixo</p>
<pre class="code"><code class="hljs">plt.<span class="hljs-title function_">figure</span>(figsize=(<span class="hljs-number">16</span>,<span class="hljs-number">5</span>))
hbars = plt.<span class="hljs-title function_">bar</span>(
    x = stocks_names, 
    height=weights[max_index, :] * <span class="hljs-number">100</span>
)
plt.<span class="hljs-title function_">bar_label</span>(hbars, fmt=<span class="hljs-string">&#x27;%.2f&#x27;</span>)
plt.<span class="hljs-title function_">ylabel</span>(<span class="hljs-string">&#x27;% de Investimento&#x27;</span>)
plt.<span class="hljs-title function_">title</span>(<span class="hljs-string">&#x27;Distribuição do investimento no portfólio selecionado&#x27;</span>)
plt.<span class="hljs-title function_">show</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2Fdba842cb1071dc6e.png?alt=media&amp;token=7ab0d8ca-93cc-46c0-9501-5d32a7dc8215" alt="" loading="lazy" decoding="async">
<p>Segundo o Sharpe Ratio devemos investir 50% de nosso orçamento em ações do Assaí (ASAI) e menos de 1% nas ações da Vale (VALE).</p>
<p>O interessante deste modelo é que ele pode ser aplica à praticamente qualquer carteira, desde que se tenha dados históricos em um mesmo período de todas as ações dela</p>
<p>Vamos visualizar os, dentro de todo o portifólio criado onde está o nosso ponto que maximiza o Sharpe Ratio</p>
<pre class="code"><code class="hljs">plt.<span class="hljs-title function_">figure</span>(figsize = (<span class="hljs-number">16</span>,<span class="hljs-number">8</span>))
# plota a volatilidade e o retorno classificado de acordo 
# com o maior valor <span class="hljs-keyword">do</span> <span class="hljs-title class_">Sharpe</span> <span class="hljs-title class_">Ratio</span>
plt.<span class="hljs-title function_">scatter</span>(
    expected_volatility, 
    expected_return, 
    c=sharpe_ratio
)
plt.<span class="hljs-title function_">xlabel</span>(<span class="hljs-string">&#x27;Volatilidade esperada&#x27;</span>)
plt.<span class="hljs-title function_">ylabel</span>(<span class="hljs-string">&#x27;Retorno Esperado&#x27;</span>)
plt.<span class="hljs-title function_">title</span>(<span class="hljs-string">&#x27;Comparação entre portfólio&#x27;</span>)
plt.<span class="hljs-title function_">colorbar</span>(label = <span class="hljs-string">&#x27;SR&#x27;</span>, extend = <span class="hljs-string">&#x27;max&#x27;</span>)
# plota em vermelho o max_index, ou seja, o ponto de maior 
# retorno e menor risco
plt.<span class="hljs-title function_">scatter</span>(
    expected_volatility[max_index], 
    expected_return[max_index], 
    c=<span class="hljs-string">&#x27;red&#x27;</span>, 
    s=<span class="hljs-number">70</span>,   
)
plt.<span class="hljs-title function_">show</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-EBPgCdTG-fIn2%2Fcontent%2F4c59b1536e60aee1.png?alt=media&amp;token=929fed0f-d4e5-4a71-b728-46371400a3f7" alt="" loading="lazy" decoding="async">
<p>Podemos observar no gráfico acima que os maiores retornos (em amarelo) estão no limite superior de nossa amostra, e cabe ao investidor avaliar o risco (eixo X) que deseja correr para alcançar aquele retorno.</p>
<p>O ponto vermelho indica o maior retorno que podemos ter com o menor risco possível.</p>
<p>Bacana, não é?</p>
<p>Como o objetivo deste texto não é ajudar na previsão de receita e sim ajudar a definir o valor de investimento baseado em dados históricos, deixo aqui o link de um texto (em inglês) que escrevi sobre o uso de uma rede neural LSTM para a predição do valor de ações, aqui mesmo no <a href="https://cutt.ly/P04UdX4" target="_blank" rel="noopener">Medium</a>.</p>
<p>Caso tenha encontrado alguma “câimbra mental” ou mesmo um erro de código por favor me avise através do e-mail <a href="mailto:marcosmhs@live.com">marcosmhs@live.com</a> e eu ficarei feliz em corrigir o texto e creditá-lo.</p>
<p>Como sempre o código completo pode ser encontrado em meu <a href="https://github.com/marcosmhs/Analise-de-acoes-usando-sharpe-ratio" target="_blank" rel="noopener">GitHub</a></p>
]]></content:encoded>
  </item>
  <item>
    <title>Avaliação de Fundos Imobiliários com Python</title>
    <link>https://www.marcosmhs.com.br/artigos/avaliacao-de-fundos-imobiliarios-com-python/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/avaliacao-de-fundos-imobiliarios-com-python/</guid>
    <pubDate>Sat, 17 Dec 2022 19:02:53 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>Python</category>
    <category>Fundos Imobiliários</category>
    <description>Investir seu rico dinheirinho é um assunto delicado, muitos tem medo de perder outros tem medo de não ganhar. Como eu me encaixo nestes dois cenários e por…</description>
    <content:encoded><![CDATA[<figure><img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-irRhtGrDll9yA%2Fcontent%2F4a658e379751a9fd.jpg?alt=media&amp;token=7bb9116d-3d41-4120-b3a4-95cd48b80ed3" alt="Photo by Towfiqu barbhuiya on Unsplash" loading="lazy" decoding="async"><figcaption>Photo by Towfiqu barbhuiya on Unsplash</figcaption></figure>
<p>Investir seu rico dinheirinho é um assunto delicado, muitos tem medo de perder outros tem medo de não ganhar. Como eu me encaixo nestes dois cenários e por ter a terrível mania de investir na alta e vender na baixa, perdendo sempre tento recorrer aos números como forma de evitar perder o pouco que sobrou.</p>
<p>Brincadeiras à parte tenho consegui algum sucesso observando alguns investidores e olhando para indicadores que ajudam a determinar se um papel vai ou não dar retorno.</p>
<p>Encontrei recentemente um script que listava os fundos imobiliários com pagamento de dividendos e aproveitei para expandir seu uso para me ajudar a encontrar aqueles que fazem mais sentido investir.</p>
<p>Vamos ao código!</p>
<pre class="code"><code class="hljs"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> webbrowser
<span class="hljs-keyword">from</span> ipywidgets <span class="hljs-keyword">import</span> interact, interact_manual</code></pre>
<p>Os dados virão do site <a href="http://www.fundsexplorer.com.br" target="_blank" rel="noopener">www.fundsexplorer.com.br</a>, para isso usei o pacote request para acessar o ranking de fundos disponíveis</p>
<pre class="code"><code class="hljs">pd.options.display.float_format = <span class="hljs-string">&#x27;{:.2f}&#x27;</span>.<span class="hljs-built_in">format</span>
page_data = requests.get(<span class="hljs-string">&quot;https://www.fundsexplorer.com.br/ranking&quot;</span>).text</code></pre>
<p>Uma vez obtido os dados do site foi necessário transformá-los em um dataframe e fazer algumas conversões.</p>
<pre class="code"><code class="hljs">df_fiis = pd.<span class="hljs-title function_">read_html</span>(page_data)[<span class="hljs-number">0</span>]

# remove os caracteres que irão impedir conversão de dados
df_fiis = df_fiis.<span class="hljs-title function_">replace</span>([<span class="hljs-string">&quot;R\$&quot;</span>, <span class="hljs-string">&quot;%&quot;</span>, <span class="hljs-string">&quot;\.&quot;</span>], <span class="hljs-string">&quot;&quot;</span>, regex = <span class="hljs-title class_">True</span>)

# substitui , por . (para permitir a transformação <span class="hljs-keyword">do</span> string em float)
df_fiis = df_fiis.<span class="hljs-title function_">replace</span>(<span class="hljs-string">&quot;,&quot;</span>, <span class="hljs-string">&quot;.&quot;</span>, regex = <span class="hljs-title class_">True</span>)

# valor <span class="hljs-keyword">do</span> P/VPA muda durante a importacão, isso é necessário para retorná-lo ao valor original
df_fiis[<span class="hljs-string">&quot;P/VPA&quot;</span>] = df_fiis[<span class="hljs-string">&quot;P/VPA&quot;</span>] / <span class="hljs-number">100</span>
df_fiis[<span class="hljs-string">&quot;VPA&quot;</span>] = pd.<span class="hljs-title function_">to_numeric</span>(df_fiis[<span class="hljs-string">&quot;VPA&quot;</span>], downcast=<span class="hljs-string">&quot;float&quot;</span>) / <span class="hljs-number">100</span></code></pre>
<p>Visualizando os dados vemos que temos 25 colunas com os dados necessários para nossa análise. No código fonte eu detalho um pouco mais algumas delas.</p>
<pre class="code"><code class="hljs">df_fiis.<span class="hljs-title function_">head</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-irRhtGrDll9yA%2Fcontent%2Fe19ccef4c15c07a8.png?alt=media&amp;token=66abde92-2646-4a62-b149-cf2b0f767414" alt="" loading="lazy" decoding="async">
<p>Neste exemplo eu vou analisar todas os fundos disponíveis até e no futuro manterei apenas aqueles que tenho maior interesse em investir. Para isso eu criei a lista fii_list com o código de todos os fundos.</p>
<pre class="code"><code class="hljs">fii_list = df_fiis[<span class="hljs-string">&#x27;Código do fundo&#x27;</span>].<span class="hljs-title function_">unique</span>().<span class="hljs-title function_">tolist</span>()</code></pre>
<p>Na sequência eu calculei a nota de todos os fundos multiplicando o:</p>
<blockquote>
<p>o Indicador calculado pela divisão do preço da cota sobre o valor do patrimonial do fundo pela Média do Dividend Yield no último ano</p>
</blockquote>
<p>Desta forma é possível identificar os fundos que podem gerar maior retorno neste período</p>
<pre class="code"><code class="hljs">filtered_fiis = df_fiis[df_fiis[<span class="hljs-string">&quot;Código do fundo&quot;</span>].<span class="hljs-title function_">isin</span>(fii_list)]
analized_fiis = filtered_fiis[[<span class="hljs-string">&quot;Código do fundo&quot;</span>, <span class="hljs-string">&quot;Setor&quot;</span>, <span class="hljs-string">&quot;Preço Atual&quot;</span>, <span class="hljs-string">&quot;Dividend Yield&quot;</span>, <span class="hljs-string">&quot;DY (3M) Média&quot;</span>, <span class="hljs-string">&quot;DY (6M) Média&quot;</span>, <span class="hljs-string">&quot;DY (12M) Média&quot;</span>, <span class="hljs-string">&quot;VPA&quot;</span>, <span class="hljs-string">&quot;P/VPA&quot;</span>]]

analized_fiis[<span class="hljs-string">&#x27;Nota&#x27;</span>] = (
                                (<span class="hljs-number">1</span> / analized_fiis[<span class="hljs-string">&#x27;P/VPA&#x27;</span>]) 
                                * pd.<span class="hljs-title function_">to_numeric</span>(df_fiis[<span class="hljs-string">&quot;DY (12M) Acumulado&quot;</span>], downcast=<span class="hljs-string">&quot;float&quot;</span>)
                           )

analized_fiis.<span class="hljs-title function_">sort_values</span>(by=[<span class="hljs-string">&quot;Nota&quot;</span>], inplace=<span class="hljs-title class_">True</span>, ascending=[<span class="hljs-title class_">False</span>])</code></pre>
<p>Ao final teremos o dataframe analized_fiis com o resultado de nossa análise, classificados da maior nota (melhor) para a menor (pior)</p>
<pre class="code"><code class="hljs">analized_fiis.<span class="hljs-title function_">nlargest</span>(<span class="hljs-number">10</span>, <span class="hljs-string">&#x27;Nota&#x27;</span>)</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-irRhtGrDll9yA%2Fcontent%2F53fe7046ee8bc087.png?alt=media&amp;token=3fc9beab-5859-44e2-81d3-894fbfbc1410" alt="" loading="lazy" decoding="async">
<p>Para ajudar em minha análise também criei uma função que retorna um determinado fundo e abre o site <em>fundsexplorer</em> com os detalhes</p>
<pre class="code"><code class="hljs">def <span class="hljs-title function_">list_fii_data</span>(fundo):
    webbrowser.<span class="hljs-title function_">open_new</span>(<span class="hljs-string">&#x27;https://www.fundsexplorer.com.br/funds/&#x27;</span> + fundo)
    <span class="hljs-keyword">return</span> analized_fiis.<span class="hljs-title function_">set_index</span>(<span class="hljs-string">&#x27;Código do fundo&#x27;</span>).loc[[fundo]]

<span class="hljs-title function_">interact</span>(
    list_fii_data, 
    fundo= analized_fiis.<span class="hljs-title function_">sort_values</span>(by=[<span class="hljs-string">&quot;Código do fundo&quot;</span>])[<span class="hljs-string">&#x27;Código do fundo&#x27;</span>].<span class="hljs-title function_">unique</span>(). <span class="hljs-title function_">tolist</span>()
    
)</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-irRhtGrDll9yA%2Fcontent%2Fe9935576586c3a2e.png?alt=media&amp;token=eb76502f-bfea-4814-9aee-9c3c4a545c12" alt="" loading="lazy" decoding="async">
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-irRhtGrDll9yA%2Fcontent%2Fd383a010285439c9.png?alt=media&amp;token=d7f771eb-b62d-42d5-8512-b844f716372d" alt="" loading="lazy" decoding="async">
<p>O código fonte pode ser acessado em meu <a href="https://github.com/marcosmhs/analise_fundo_imobiliario/" target="_blank" rel="noopener">github</a>!</p>
<p>Caso encontre algum erro ou câimbra mental me avise no <a href="mailto:marcosmhs@live.com">marcosmhs@live.com</a> e ficarei feliz em fazer os ajustes garantindo o devido crédito à sua contribuição. :)</p>
]]></content:encoded>
  </item>
  <item>
    <title>Complete Hive Example on Flutter App</title>
    <link>https://www.marcosmhs.com.br/artigos/complete-hive-example-on-flutter-app/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/complete-hive-example-on-flutter-app/</guid>
    <pubDate>Wed, 14 Sep 2022 01:10:03 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>Flutter</category>
    <category>Hive</category>
    <description>Hive is one of the most interesting resources to store and access local data on Flutter applications. And for me the best feature is the ability to store and…</description>
    <content:encoded><![CDATA[<figure><img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2F099df0f8a1699528.jpg?alt=media&amp;token=66e2d4fb-ccea-4da0-9b63-d8a1b85a7210" alt="Photo by Caspar Camille Rubin on Unsplash" loading="lazy" decoding="async"><figcaption>Photo by Caspar Camille Rubin on Unsplash</figcaption></figure>
<p>Hive is one of the most interesting resources to store and access local data on Flutter applications. And for me the best feature is the ability to store and recover Dart classes. To do that Hive uses Type Adapters, a method that transform your classes in data that can be stored.</p>
<blockquote>
<p>On next I will resume in a few steps how to use the Hive with Type Adaptors but I´m recommend you see all the steps in detail and execute these codes in your computer you by downloading the complete exemple on <a href="https://github.com/marcosmhs/hive_example" target="_blank" rel="noopener">my GitHub</a></p>
</blockquote>
<h2 id="1-install-packages">1. Install packages</h2>
<p>The necessary packages to use Hive are:</p>
<ul>
<li>hive</li>
<li>hive_flutter</li>
<li>hive_generator</li>
<li>build_runner</li>
</ul>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2F183102ac7f63fc84.jpg?alt=media&amp;token=9bb1a6b7-91e7-4968-ab60-ddea89c46766" alt="" loading="lazy" decoding="async">
<h2 id="2-initiate-flutter">2. Initiate flutter</h2>
<p>Once the packages installed you need to initiate Hive on your app, the <em>main</em>() method on <em>main.dart</em> is a good place for that.</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2F5447d1169a78aed7.jpg?alt=media&amp;token=5979ed70-7667-458a-9e28-10868d63e83d" alt="" loading="lazy" decoding="async">
<h2 id="3-create-adapter-file">3. Create adapter file</h2>
<p>As we are working to store entire classes, on the class file, in this case <em>person.dart</em> is necessary indicate the file that will be created by Hive generator. I will talk more about the adapter file on step 5 :)</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2Fb24de7124d82906c.jpg?alt=media&amp;token=214d9155-cc49-4656-90e5-b115974f25eb" alt="" loading="lazy" decoding="async">
<p><em>Important: you will need to do that in all classes files that you want to store!</em></p>
<h2 id="4-indicate-ids-to-classes-and-atributes">4. Indicate IDs to classes and atributes</h2>
<p>With the indication of adaptor file in the class you need to indicate to Hive generator witch classes and columns will be storage. Is importante to have in mind that each class should be a unique <em>typeId</em> and inside the classes the fields also should be a unique ID</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2F4d4f85346c588cb4.jpg?alt=media&amp;token=bea2c6da-fdb2-4403-9824-f02d6bc3d4d3" alt="" loading="lazy" decoding="async">
<h2 id="5-run-flutter-command">5. Run flutter command</h2>
<p>After all classes be prepared run the command below on your terminal</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2Fc0a7982c3fdfe045.jpg?alt=media&amp;token=5772c9a6-0835-4e62-a100-439eca854fd3" alt="" loading="lazy" decoding="async">
<p>The command <em><strong>flutter packages pub run build_runner build</strong></em> will read all classes in your code and create adapters to translate your classes to binary data and vice versa when you read de stored data. These files will use the name that you indicate on step 3</p>
<h2 id="6-register-adapter">6. Register adapter</h2>
<p>After the execution of the previous step each class with and <a href="http://twitter.com/HiveType" target="_blank" rel="noopener">@HiveType</a> will have and adapter and needed to be register, I’m also recommend the use of main method</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2F07bc999992e87de8.jpg?alt=media&amp;token=7582526d-dccf-419f-ba17-e17112bbfa6f" alt="" loading="lazy" decoding="async">
<h2 id="7-opening-the-box">7. Opening the box</h2>
<p>Now that your application is ready it´s time to understand an importante feature of Hive: the data are stored in boxes and to save and acesses your data you need to open those boxes. To do that I´m use the method bellow to verify if a box is already open and return it or if it needs to be opened.</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2F9b607330aa3b2689.jpg?alt=media&amp;token=c2fa7c86-8a41-4051-8fd2-790af3556833" alt="" loading="lazy" decoding="async">
<h2 id="8-crud">8. CRUD</h2>
<p>After the opening the data box, you can start the CRUD operations, like the images below</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2F680df3cb8a04396b.jpg?alt=media&amp;token=acb7cfda-a56c-4790-8639-2b0b90ac9ee3" alt="" loading="lazy" decoding="async">
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2F63c30d63ca8b2f6d.jpg?alt=media&amp;token=dcd88482-bd1f-4373-8ac4-b57f4f1406fb" alt="" loading="lazy" decoding="async">
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2F4d4aea25687b3c89.jpg?alt=media&amp;token=9088608f-9b2c-40bd-acc3-4e356d1f7254" alt="" loading="lazy" decoding="async">
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-VaJYplD8jN8yz%2Fcontent%2F8b30025dd7bd4758.jpg?alt=media&amp;token=f5d962d2-ccb3-4114-819b-8af6420af228" alt="" loading="lazy" decoding="async">
<blockquote>
<p>You can find the Hive documentation and more detains on <a href="https://docs.hivedb.dev/#/" target="_blank" rel="noopener">Hive Docs website</a></p>
</blockquote>
]]></content:encoded>
  </item>
  <item>
    <title>Stock prediction LSTM Neural Network function</title>
    <link>https://www.marcosmhs.com.br/artigos/stock-prediction-lstm-neural-network-function/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/stock-prediction-lstm-neural-network-function/</guid>
    <pubDate>Mon, 12 Sep 2022 13:57:42 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>RStudio</category>
    <category>Redes Neurais</category>
    <description>This method creates a LSTM neural net capable of predict a stock time series using Keras.</description>
    <content:encoded><![CDATA[<figure><img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-U2RjpPls1v627%2Fcontent%2F78dd00ac58006637.jpg?alt=media&amp;token=8dbc233f-c0af-415e-8a60-27ad16b4e2e1" alt="Photo by Sigmund on Unsplash" loading="lazy" decoding="async"><figcaption>Photo by Sigmund on Unsplash</figcaption></figure>
<p>This method creates a LSTM neural net capable of predict a stock time series using Keras.</p>
<p>I wrote about LSTM and time series on <a href="https://rpubs.com/marcosmhs/rede_lstm_predicao_dolar" target="_blank" rel="noopener">this article</a> in RPubs site (in Portuguese).</p>
<p>The code of the method could be downloaded on my <a href="https://github.com/marcosmhs/LSTM-Stock-prediction-function" target="_blank" rel="noopener">Github</a>.</p>
<h2 id="execution-steps">Execution steps</h2>
<p>The method structure could be resumed in the image bellow</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-U2RjpPls1v627%2Fcontent%2Fb0707238d760108a.png?alt=media&amp;token=3c795b43-5dfc-4ddf-b2b1-9c2882a44c7a" alt="" loading="lazy" decoding="async">
<h2 id="code-examples">Code Examples</h2>
<p>Method creation:</p>
<pre class="code"><code class="hljs">#using <span class="hljs-title class_">GitHub</span> <span class="hljs-title class_">Strocture</span></code></pre>
<pre class="code"><code class="hljs"><span class="hljs-title function_">source</span>(<span class="hljs-string">&#x27;lstm_stock_function.R&#x27;</span>)</code></pre>
<p>On a first example I with use META (Facebook, WhatsApp, Instagram, etc) stocks and for now I don´t need a ARIMA comparison</p>
<pre class="code"><code class="hljs">return_meta &lt;- 
    <span class="hljs-title function_">lstm_stock</span>(
      stock_name = <span class="hljs-string">&#x27;META&#x27;</span>, 
      start_date = <span class="hljs-string">&#x27;2019-01-01&#x27;</span>, 
      lstm_executions = <span class="hljs-number">10</span>, 
      lstm_verbose = F)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">## [1] &quot;-----------------------------------&quot;</span>
<span class="hljs-comment">## [1] &quot;Execution completed...&quot;</span>
<span class="hljs-comment">## $parameters</span>
<span class="hljs-comment">##   stock_name start_date   end_date arima_compare</span>
<span class="hljs-comment">## 1       META 2019-01-01 2022-09-12         FALSE</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">## [1] &quot;MSE&quot;</span>
<span class="hljs-comment">## 1  2.53</span></code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-U2RjpPls1v627%2Fcontent%2Fcbfb63bf377160fe.png?alt=media&amp;token=b880319a-1acb-4819-a8f9-8c76071b4dc8" alt="" loading="lazy" decoding="async">
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-U2RjpPls1v627%2Fcontent%2Fc718c7640c5dc0d7.png?alt=media&amp;token=dc8bdffe-0f60-492d-a53e-ba1f50ad0eb4" alt="" loading="lazy" decoding="async">
<p>As we can see the data shows us a growing trend and the normalization was needed to create the neural net.</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-U2RjpPls1v627%2Fcontent%2F0d73d73b07dee480.png?alt=media&amp;token=98121d75-b478-4641-91cd-8ed601f3a367" alt="" loading="lazy" decoding="async">
<p>The prediction plot show that the model was capable to predict results remarkably close to the real prices</p>
<p>On a second example the <strong>lstm_stock</strong> will use data from Petrobrás (brazilian oil company). The data will be extract from Bovespa (brazilian stock market) from 2015 until today. The method will execute a LSTM neural net with 10 iterations and in the end will also execute and ARIMA model to compare the results</p>
<pre class="code"><code class="hljs">return_petr4 <span class="hljs-operator">&lt;-</span> 
    lstm_stock<span class="hljs-punctuation">(</span>
      origin <span class="hljs-operator">=</span> <span class="hljs-string">&#x27;^BVSP&#x27;</span><span class="hljs-punctuation">,</span> 
      stock_name <span class="hljs-operator">=</span> <span class="hljs-string">&#x27;PETR4.SA&#x27;</span><span class="hljs-punctuation">,</span> 
      start_date <span class="hljs-operator">=</span> <span class="hljs-string">&#x27;2015-01-01&#x27;</span><span class="hljs-punctuation">,</span> 
      lstm_executions <span class="hljs-operator">=</span> <span class="hljs-number">10</span><span class="hljs-punctuation">,</span> 
      arima_compare <span class="hljs-operator">=</span> <span class="hljs-built_in">T</span><span class="hljs-punctuation">,</span>
      lstm_verbose <span class="hljs-operator">=</span> <span class="hljs-built_in">F</span><span class="hljs-punctuation">)</span>

<span class="hljs-comment">## [1] &quot;Execution completed...&quot;</span>
<span class="hljs-comment">## $parameters</span>
<span class="hljs-comment">##   stock_name start_date   end_date arima_compare</span>
<span class="hljs-comment">## 1   PETR4.SA 2015-01-01 2022-09-12          TRUE</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">## [1] &quot;MSE&quot;</span>
<span class="hljs-comment">##   variable        value</span>
<span class="hljs-comment">## 1     lstm 4.203284e-01</span>
<span class="hljs-comment">## 2    arima 7.725121e-05</span></code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-U2RjpPls1v627%2Fcontent%2F01260677cce7971b.png?alt=media&amp;token=2fbe710c-08a1-48e4-a5e5-74301e95da9b" alt="" loading="lazy" decoding="async">
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-U2RjpPls1v627%2Fcontent%2Fe8833bb95206910d.png?alt=media&amp;token=5db11c6c-2d9f-4a5c-9439-bbd499e1f3f1" alt="" loading="lazy" decoding="async">
<p>Again, the data shows us a growing trend and the normalization was needed to create the neural net.</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-U2RjpPls1v627%2Fcontent%2F49de25242565970b.png?alt=media&amp;token=de7f3647-7fd3-42cc-84c7-8792e331aa8f" alt="" loading="lazy" decoding="async">
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-U2RjpPls1v627%2Fcontent%2F4d6720dc450fc8a8.png?alt=media&amp;token=0c8bde4b-dbb1-49f5-b3a6-8cbf4cd3d7fa" alt="" loading="lazy" decoding="async">
<p>The LSTM prediction chart (on left) show us some error on the predicted value, while the ARIMA model present a better result. That perception could be confirmed by the MSE results:</p>
<pre class="code"><code class="hljs"><span class="hljs-comment">## [1] &quot;MSE&quot;</span>
<span class="hljs-comment">##   variable        value</span>
<span class="hljs-comment">## 1     lstm 4.203284e-01</span>
<span class="hljs-comment">## 2    arima 7.725121e-05</span></code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-U2RjpPls1v627%2Fcontent%2Fdceb28ad4708ab83.png?alt=media&amp;token=80ef11f4-ecff-4938-99d6-baa7d3ed5c53" alt="" loading="lazy" decoding="async">
<p>To end this text, if you find some bug or “brain cramp” please e-mail me on <a href="mailto:marcosmhs@live.com">marcosmhs@live.com</a> and I will be glad on correct the code and register your name on the credits.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Análise de risco na liberação de empréstimos</title>
    <link>https://www.marcosmhs.com.br/artigos/analise-de-risco-na-liberacao-de-emprestimos/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/analise-de-risco-na-liberacao-de-emprestimos/</guid>
    <pubDate>Tue, 06 Sep 2022 00:47:27 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>RStudio</category>
    <category>Randon Forest</category>
    <description>A maleabilidade e adaptabilidade das florestas aleatórias são uma das muitas vantagens deste tipo de modelo. Da previsão do tempo à análise de risco de…</description>
    <content:encoded><![CDATA[<figure><img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-z8KT26FOLL5Xd%2Fcontent%2Fc1c2e433a4761271.jpg?alt=media&amp;token=b9269c3d-9edf-408f-b6d0-14f5fbbf53ef" alt="Photo by Daniel Thomas on Unsplash" loading="lazy" decoding="async"><figcaption>Photo by Daniel Thomas on Unsplash</figcaption></figure>
<p>A maleabilidade e adaptabilidade das florestas aleatórias são uma das muitas vantagens deste tipo de modelo. Da previsão do tempo à análise de risco de crédito, esse tipo de método tem muitas aplicações. E risco de crédito é o tema desse artigo.</p>
<p>Vagando pelo banco de dados infinito do Kaggle encontrei um banco de dados de com registros de 887 mil registros de empréstimos com dados dos mutuários e a situação do empréstimo.</p>
<p>Com o conjunto de dados em meu computador, iniciei a análise inicial para entender as dimensões e as variáveis.</p>
<p>Mas antes, preciso importar as bibliotecas necessárias e para isso gosto de usar esse método que as importa e instala automaticamente:</p>
<pre class="code"><code class="hljs">pkgs <span class="hljs-operator">=</span> 
 <span class="hljs-built_in">c</span><span class="hljs-punctuation">(</span>“plotly”<span class="hljs-punctuation">,</span>”tidyverse”<span class="hljs-punctuation">,</span>”reshape2<span class="hljs-string">&quot;,”knitr”,”kableExtra”,”rgl”,”car”,
 “jtools”, “data.table”, “GGally”, “cowplot”, “janitor”,
 “funModeling”, “modeldata”, “Metrics”)</span></code></pre>
<pre class="code"><code class="hljs"><span class="hljs-keyword">if</span>(<span class="hljs-title function_">sum</span>(<span class="hljs-keyword">as</span>.<span class="hljs-title function_">numeric</span>(!pkgs %<span class="hljs-keyword">in</span>% installed.<span class="hljs-title function_">packages</span>())) != <span class="hljs-number">0</span>){
 install = pkgs[!pkgs %<span class="hljs-keyword">in</span>% installed.<span class="hljs-title function_">packages</span>()]
 <span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:<span class="hljs-title function_">length</span>(install)) {
 install.<span class="hljs-title function_">packages</span>(install, dependencies = T)
 <span class="hljs-title function_">break</span>()}
 <span class="hljs-title function_">sapply</span>(pkgs, require, character = T) 
} <span class="hljs-keyword">else</span> {
 <span class="hljs-title function_">sapply</span>(pkgs, require, character = T) 
}</code></pre>
<p>Com os pacotes instalados podemos fazer a importação dos dados utilizando o comando fread:</p>
<pre class="code"><code class="hljs">data = <span class="hljs-title function_">fread</span>(<span class="hljs-string">&quot;loans.csv&quot;</span>)</code></pre>
<blockquote>
<p>Obs: eu sei que em R o correto é fazer uma atribuição utilizando &lt;-, porém meu cérebro não aceita bem isso e sigo usando o =. Por favor não me julguem :)</p>
</blockquote>
<p>Temos duas colunas de identificação nesta base, id e member_id ambas desnecessárias para nossa análise. Manterei a coluna id como identificador das linhas e removerei member_id.</p>
<pre class="code"><code class="hljs">data_cleaned <span class="hljs-operator">=</span>
   data <span class="hljs-operator">%</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">%</span>
   # <span class="hljs-keyword">column</span> id transformed <span class="hljs-keyword">in</span> <span class="hljs-type">row</span> name
   column_to_rownames(&quot;id&quot;) <span class="hljs-operator">%</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">%</span>
   # removing <span class="hljs-keyword">column</span> member_id
   <span class="hljs-keyword">select</span>(everything(), <span class="hljs-operator">-</span>member_id)</code></pre>
<p>Após a remoção destas duas colunas o dataset permanece ainda com 72 colunas. Será necessário fazer a análise de cada uma delas para determinar aquelas que são relevantes para o modelo. Observe que ao invés de trabalhar no dataset original eu criei um novo, com isso mantenho os dados originais intactos e evito novas importações. A partir deste ponto todo o trabalho será feito com o dataset data_cleaned.</p>
<h2 id="analise-de-variaveis-categoricas">Análise de variáveis categóricas</h2>
<p>As random forests trabalham bem com variáveis categóricas, porém é importante verificar a quantidade de “categorias” presentes em cada variável para que reduzamos a amplitude das informações sem perdermos sua objetividade. Muitas categorias podem tornar a análise inviável fragmentando os resultados gerados. Lembre-se, modelos preditivos tentam prever o futuro e dar muitas opções aumenta a taxa de erro podendo inviabilizar o resultado.</p>
<p>Iniciaremos listando as variáveis categóricas, que nesta base de dados são todas do tipo texto.</p>
<pre class="code"><code class="hljs">data_cleaned <span class="hljs-operator">%&gt;%</span> 
   <span class="hljs-comment"># selecting character columns becouse I  </span>
   select_if<span class="hljs-punctuation">(</span><span class="hljs-built_in">is.character</span><span class="hljs-punctuation">)</span> <span class="hljs-operator">%&gt;%</span> 
   <span class="hljs-built_in">names</span><span class="hljs-punctuation">(</span><span class="hljs-punctuation">)</span> <span class="hljs-operator">%&gt;%</span>
   reshape2<span class="hljs-operator">::</span>melt<span class="hljs-punctuation">(</span><span class="hljs-punctuation">)</span></code></pre>
<pre class="code"><code class="hljs">                       <span class="hljs-keyword">value</span>
<span class="hljs-number">1</span>                       term
<span class="hljs-number">2</span>                      grade
<span class="hljs-number">3</span>                  sub_grade
<span class="hljs-number">4</span>                  emp_title
<span class="hljs-number">5</span>                 emp_length
<span class="hljs-number">6</span>             home_ownership
<span class="hljs-number">7</span>        verification_status
<span class="hljs-number">8</span>                    issue_d
<span class="hljs-number">9</span>                loan_status
<span class="hljs-number">10</span>                pymnt_plan
<span class="hljs-number">11</span>                       url
<span class="hljs-number">12</span>                      <span class="hljs-keyword">desc</span>
<span class="hljs-number">13</span>                   purpose
<span class="hljs-number">14</span>                     title
<span class="hljs-number">15</span>                  zip_code
<span class="hljs-number">16</span>                addr_state
<span class="hljs-number">17</span>          earliest_cr_line
<span class="hljs-number">18</span>       initial_list_status
<span class="hljs-number">19</span>              last_pymnt_d
<span class="hljs-number">20</span>              next_pymnt_d
<span class="hljs-number">21</span>        last_credit_pull_d
<span class="hljs-number">22</span>          application_type
<span class="hljs-number">23</span> verification_status_joint</code></pre>
<p>Vamos primeiro falar sobre nossa variável alvo a loan_status, que indica qual a situação daquele empréstimo.</p>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">tabyl</span>(loan_status) %&gt;% 
   <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% 
   <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs">                                          loan_status      n percent
                                              <span class="hljs-title class_">Current</span> <span class="hljs-number">601779</span>   <span class="hljs-number">68.0</span>%
                                           <span class="hljs-title class_">Fully</span> <span class="hljs-title class_">Paid</span> <span class="hljs-number">207723</span>   <span class="hljs-number">23.5</span>%
                                          <span class="hljs-title class_">Charged</span> <span class="hljs-title class_">Off</span>  <span class="hljs-number">45248</span>    <span class="hljs-number">5.1</span>%
                                   <span class="hljs-title class_">Late</span> (<span class="hljs-number">31</span>-<span class="hljs-number">120</span> days)  <span class="hljs-number">11591</span>    <span class="hljs-number">1.3</span>%
                                               <span class="hljs-title class_">Issued</span>   <span class="hljs-number">8460</span>    <span class="hljs-number">1.0</span>%
                                      <span class="hljs-title class_">In</span> <span class="hljs-title class_">Grace</span> <span class="hljs-title class_">Period</span>   <span class="hljs-number">6253</span>    <span class="hljs-number">0.7</span>%
                                    <span class="hljs-title class_">Late</span> (<span class="hljs-number">16</span>-<span class="hljs-number">30</span> days)   <span class="hljs-number">2357</span>    <span class="hljs-number">0.3</span>%
                                              <span class="hljs-title class_">Default</span>   <span class="hljs-number">1219</span>    <span class="hljs-number">0.1</span>%
  <span class="hljs-title class_">Does</span> not meet the credit policy. <span class="hljs-title class_">Status</span>:<span class="hljs-title class_">Charged</span> <span class="hljs-title class_">Off</span>    <span class="hljs-number">761</span>    <span class="hljs-number">0.1</span>%</code></pre>
<p>Como pode-se observar, um empréstimo pode ter vários status, dependendo do momento:</p>
<p>· Current: indica que o empréstimo está ativo e com pagamentos em dia</p>
<p>· Fully Paid: empréstimos totalmente pagos e finalizados</p>
<p>· Charged Off: indica que a dívida do empréstimo é incobrável.</p>
<p>· Late (31-120 days): empréstimo possui pagamentos com atraso entre 31 e 120 dias</p>
<p>· Issued: empréstimos recentemente liberados, ainda sem pagamentos emitidos ou recebidos</p>
<p>· In Grace Period: empréstimo possui pagamento em período de carência, ou seja, vencido entre 1 e 15 dias</p>
<p>· Late (16-30 days): empréstimo possui pagamentos com atraso entre 16 e 30 dias</p>
<p>· Default: quando o titular do empréstimo não é capaz de realizar pagamentos por um longo período (superior a 120 dias)</p>
<p>· Does not meet the credit policy. Status:Charged Off: solicitação do empréstimo é cancelada quando o titular possui dívidas consideradas incobráveis.</p>
<p>Avaliando os possíveis valores podemos separá-los em três grupos:</p>
<p><strong>Bons pagadores</strong></p>
<p>· Fully Paid</p>
<p><strong>Maus pagadores</strong></p>
<p>· In Grace Period, Late (16-30 days) e Late (31-120 days) e Default indicam potenciais atrasos em pagamento</p>
<p>· Charged Off indica uma dívida que não será recebida sem a necessidade de apoio jurídico</p>
<p><strong>Indefinido (situação não indica se os pagamentos podem ou não atrasar:</strong></p>
<p>· Current empréstimos com pagamento em dia não necessariamente indicam que serão totalmente pagos dado que pode haver atraso em parcelas futuras</p>
<p>· Issued: e Does not meet the credit policy. Status:Charged Off representam empréstimos que não iniciaram ou nunca serão iniciados</p>
<p>Como eu comentei anteriormente é importante tentarmos reduzir a quantidade de categorias sempre que possível, neste caso, podemos transformar a coluna loan_statusem uma nova coluna com 2 valores que indiquem a informação que desejamos: bons e maus pagadores. Também podemos reduzir a quantidade de dados, removendo da base de dados empréstimos que não possuem informações relevantes, neste caso aqueles com a situação considerada indefinida.</p>
<p>Vamos começar pela exclusão dos lançamentos que não serão utilizados no modelo.</p>
<pre class="code"><code class="hljs">data_cleaned = 
   data_cleaned %&gt;%
   <span class="hljs-title function_">filter</span>(!loan_status %<span class="hljs-keyword">in</span>% <span class="hljs-title function_">c</span>(
      <span class="hljs-string">&quot;Current&quot;</span>, 
      <span class="hljs-string">&quot;Does not meet the credit policy. Status:Charged Off&quot;</span>, 
      <span class="hljs-string">&quot;Issued&quot;</span>
   )
)</code></pre>
<p>Agora vamos simplificar a nossa variável resposta:</p>
<pre class="code"><code class="hljs">data_cleaned <span class="hljs-operator">=</span>
   data_cleaned <span class="hljs-operator">%</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">%</span>
   # creates a <span class="hljs-keyword">new</span> <span class="hljs-keyword">column</span> <span class="hljs-keyword">with</span> the <span class="hljs-keyword">value</span> <span class="hljs-keyword">from</span> good <span class="hljs-keyword">and</span> bad borrow
   mutate(
      target <span class="hljs-operator">=</span> ifelse(
         loan_status <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">&#x27;Fully Paid&#x27;</span>, 
         <span class="hljs-string">&#x27;Good borrow&#x27;</span>,
         <span class="hljs-string">&#x27;Bad borrow&#x27;</span>)) <span class="hljs-operator">%</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">%</span>
   # <span class="hljs-keyword">select</span> <span class="hljs-keyword">all</span> columns minus the loan status
   <span class="hljs-keyword">select</span>(everything(), <span class="hljs-operator">-</span>loan_status)</code></pre>
<blockquote>
<p>Obs: mantive os valores em inglês para seguir o padrão da base. Utilizei a função ifelse para simplificar o código, já que somente os empréstimos totalmente pagos são considerados bons.</p>
</blockquote>
<p>Vamos executar novamente a verificação dos valores agora na variável target para verificarmos como ficaram distribuídos os novos valores.</p>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">tabyl</span>(target) %&gt;% 
   <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% 
   <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs">       target      n percent
  <span class="hljs-title class_">Good</span> borrow <span class="hljs-number">207723</span>   <span class="hljs-number">75.7</span>%
   <span class="hljs-title class_">Bad</span> borrow  <span class="hljs-number">66668</span>   <span class="hljs-number">24.3</span>%</code></pre>
<p>Seguindo a análise com as demais variáveis categóricas, eu as separei em 3 grupos:</p>
<h3 id="grupo-1-variaveis-que-serao-deixadas-como-estao">Grupo 1 — Variáveis que serão deixadas como estão</h3>
<p>Estas variáveis não precisam de tratamento. Apenas uma observação sobre a variável addr_state, embora ela possua muitas categorias (estados americanos) entendo que ela é relevante pois pode ajudar a indicar em quais estados existe maior chance de calote na dívida.</p>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">tabyl</span>(emp_length) %&gt;% 
   <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;%
   <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##  emp_length     n percent</span>
<span class="hljs-comment">##   10+ years 83448   30.4%</span>
<span class="hljs-comment">##     2 years 25479    9.3%</span>
<span class="hljs-comment">##    &lt; 1 year 22738    8.3%</span>
...</code></pre>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">tabyl</span>(addr_state) %&gt;% 
   <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% 
   <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##  addr_state     n percent</span>
<span class="hljs-comment">##          CA 46195   16.8%</span>
<span class="hljs-comment">##          NY 23446    8.5%</span>
<span class="hljs-comment">##          TX 21012    7.7%</span>
...</code></pre>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">tabyl</span>(term) %&gt;% 
   <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% 
   <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##       term      n percent</span>
<span class="hljs-comment">##  36 months 209857   76.5%</span>
<span class="hljs-comment">##  60 months  64534   23.5%</span></code></pre>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">tabyl</span>(home_ownership) %&gt;% 
   <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% 
   <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##  home_ownership      n percent</span>
<span class="hljs-comment">##        MORTGAGE 134317   49.0%</span>
<span class="hljs-comment">##            RENT 115685   42.2%</span>
<span class="hljs-comment">##             OWN  24204    8.8%</span>
...</code></pre>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">tabyl</span>(purpose) %&gt;% 
   <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% 
   <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##             purpose      n percent</span>
<span class="hljs-comment">##  debt_consolidation 162080   59.1%</span>
<span class="hljs-comment">##         credit_card  53936   19.7%</span>
<span class="hljs-comment">##    home_improvement  16142    5.9%</span>
...</code></pre>
<h3 id="grupo-2-variaveis-que-serao-removidas">Grupo 2 — Variáveis que serão removidas</h3>
<p>Estas variáveis trazem informações unitárias, como observações de cada empréstismo, URL com informações da solicitação, CEP do cliente e datas de aprovação.</p>
<pre class="code"><code class="hljs"><span class="hljs-comment"># the zip code isn´t an option becose the state code will be used as a location info </span>
<span class="hljs-comment"># commented to avoid unnecessary processing</span>
<span class="hljs-comment">#data_cleaned %&gt;% </span>
<span class="hljs-comment">#   tabyl(zip_code) %&gt;% adorn_pct_formatting() %&gt;% arrange(desc(n))</span>

<span class="hljs-comment"># month when loand was funded </span>
<span class="hljs-comment"># commented to avoid unnecessary processing</span>
<span class="hljs-comment">#data %&gt;% </span>
<span class="hljs-comment">#   tabyl(issue_d) %&gt;% adorn_pct_formatting() %&gt;% arrange(desc(n))</span>

<span class="hljs-comment"># indicate of the bank verified the borrowers&#x27; </span>
data_cleaned <span class="hljs-operator">%&gt;%</span> 
   tabyl<span class="hljs-punctuation">(</span>verification_status<span class="hljs-punctuation">)</span> <span class="hljs-operator">%&gt;%</span> 
   adorn_pct_formatting<span class="hljs-punctuation">(</span><span class="hljs-punctuation">)</span> <span class="hljs-operator">%&gt;%</span> 
   arrange<span class="hljs-punctuation">(</span>desc<span class="hljs-punctuation">(</span>n<span class="hljs-punctuation">)</span><span class="hljs-punctuation">)</span></code></pre>
<pre class="code"><code class="hljs">##  verification_status      n percent
##             <span class="hljs-title class_">Verified</span> <span class="hljs-number">100925</span>   <span class="hljs-number">36.8</span>%
##         <span class="hljs-title class_">Not</span> <span class="hljs-title class_">Verified</span>  <span class="hljs-number">90739</span>   <span class="hljs-number">33.1</span>%
##      <span class="hljs-title class_">Source</span> <span class="hljs-title class_">Verified</span>  <span class="hljs-number">82727</span>   <span class="hljs-number">30.1</span>%</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment"># month that credit line was opened </span>
<span class="hljs-comment"># commented to avoid unnecessary processing</span>
<span class="hljs-comment">#data_cleaned %&gt;% </span>
<span class="hljs-comment">#   tabyl(earliest_cr_line) %&gt;% adorn_pct_formatting() %&gt;% arrange(desc(n))</span>

<span class="hljs-comment"># commented to avoid unnecessary processing </span>
<span class="hljs-comment">#data_cleaned %&gt;% </span>
<span class="hljs-comment">#   tabyl(emp_title) %&gt;% adorn_pct_formatting() %&gt;% arrange(desc(n))</span>

<span class="hljs-comment"># that variable have the same value for almost the role dataset.</span>
data_cleaned <span class="hljs-operator">%&gt;%</span> 
   tabyl<span class="hljs-punctuation">(</span>pymnt_plan<span class="hljs-punctuation">)</span> <span class="hljs-operator">%&gt;%</span> 
   adorn_pct_formatting<span class="hljs-punctuation">(</span><span class="hljs-punctuation">)</span> <span class="hljs-operator">%&gt;%</span> 
   arrange<span class="hljs-punctuation">(</span>desc<span class="hljs-punctuation">(</span>n<span class="hljs-punctuation">)</span><span class="hljs-punctuation">)</span></code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##  pymnt_plan      n percent</span>
<span class="hljs-comment">##           n 274384  100.0%</span>
<span class="hljs-comment">##           y      7    0.0%</span></code></pre>
<pre class="code"><code class="hljs"># commented to avoid unnecessary processing
#data_cleaned %&gt;% 
#   <span class="hljs-title function_">tabyl</span>(url) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))

# commented to avoid unnecessary processing
#data_cleaned %&gt;% 
#   <span class="hljs-title function_">tabyl</span>(desc) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))

# commented to avoid unnecessary processing
#data_cleaned %&gt;% 
#   <span class="hljs-title function_">tabyl</span>(title) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))

# next payment date
# commented to avoid unnecessary processing
#data_cleaned %&gt;% 
#   <span class="hljs-title function_">tabyl</span>(next_pymnt_d) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))

# commented to avoid unnecessary processing
#data_cleaned %&gt;% 
#   <span class="hljs-title function_">tabyl</span>(last_credit_pull_d) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))

data_cleaned %&gt;% 
   <span class="hljs-title function_">tabyl</span>(application_type) %&gt;% 
   <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% 
   <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##  application_type      n percent</span>
<span class="hljs-comment">##        INDIVIDUAL 274385  100.0%</span>
<span class="hljs-comment">##             JOINT      6    0.0%</span></code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment"># last payment date</span>
<span class="hljs-comment"># commented to avoid unnecessary processing</span>
<span class="hljs-comment">#data_cleaned %&gt;% </span>
<span class="hljs-comment"># tabyl(last_pymnt_d) %&gt;% adorn_pct_formatting() %&gt;% rrange(desc(n))</span></code></pre>
<blockquote>
<p>Obs: mantive as variáveis com mais categorias comentadas para evitar processamento desnecessário e que o output da execução transforme este texto em uma enciclopédia.</p>
</blockquote>
<h3 id="grupo-3-variaveis-sem-informacoes">Grupo 3 — Variáveis sem informações</h3>
<p>Este é para mim o único problema com esta base de dados, a falta de um dicionário de dados que indique a função de cada variável e os possíveis valores que podem ser armazenados em cada uma.</p>
<p>Dentro da análise de variáveis categóricas 3 delas não possuem qualquer indicador do que sejam os valores armazenados ou seu objetivo e por isso tomei a decisão de removê-las da base</p>
<p>Embora gradee sub_grade indiquem o agrupamento dos empréstimos seus valores não são claros, não deixam claro o que significa cada um dos grupos.</p>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">tabyl</span>(grade) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##  grade     n percent</span>
<span class="hljs-comment">##      B 79917   29.1%</span>
<span class="hljs-comment">##      C 71584   26.1%</span>
<span class="hljs-comment">##      D 45682   16.6%</span>
...</code></pre>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">tabyl</span>(sub_grade) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##  sub_grade     n percent</span>
<span class="hljs-comment">##         B3 18852    6.9%</span>
<span class="hljs-comment">##         B4 17895    6.5%</span>
<span class="hljs-comment">##         C1 16112    5.9%</span>
...</code></pre>
<pre class="code"><code class="hljs">data_cleaned %&gt;%  
   <span class="hljs-title function_">tabyl</span>(initial_list_status) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##  initial_list_status      n percent</span>
<span class="hljs-comment">##                    f 193471   70.5%</span>
<span class="hljs-comment">##                    w  80920   29.5%</span></code></pre>
<p>Uma vez selecionadas as variáveis que não serão utilizadas, faremos a exclusão delas:</p>
<pre class="code"><code class="hljs">data_cleaned <span class="hljs-operator">=</span>
   data_cleaned <span class="hljs-operator">%</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">%</span>
   <span class="hljs-keyword">select</span>(
    everything(), 
    # unnecessary variables
    <span class="hljs-operator">-</span>issue_d, <span class="hljs-operator">-</span>url, <span class="hljs-operator">-</span>pymnt_plan, <span class="hljs-operator">-</span><span class="hljs-keyword">desc</span>, <span class="hljs-operator">-</span>title, 
    <span class="hljs-operator">-</span>earliest_cr_line,<span class="hljs-operator">-</span>verification_status, 
    <span class="hljs-operator">-</span>emp_title, <span class="hljs-operator">-</span>next_pymnt_d, <span class="hljs-operator">-</span>last_credit_pull_d, <span class="hljs-operator">-</span>application_type,
    <span class="hljs-operator">-</span>zip_code, <span class="hljs-operator">-</span>last_pymnt_d,
    # variables <span class="hljs-keyword">without</span> details
    <span class="hljs-operator">-</span>grade, <span class="hljs-operator">-</span>sub_grade, <span class="hljs-operator">-</span>initial_list_status)</code></pre>
<p>Para finalizar a análise e preparação das variáveis qualitativas é necessário um último passo, transformando-as em variáveis do tipo factor. Para isso vamos primeiro conferir quais são as variáveis texto que precisamos converter.</p>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">select_if</span>(<span class="hljs-keyword">is</span>.character) %&gt;% 
   <span class="hljs-title function_">names</span>() %&gt;%
   reshape2::<span class="hljs-title function_">melt</span>()</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##                       value</span>
<span class="hljs-comment">## 1                      term</span>
<span class="hljs-comment">## 2                emp_length</span>
<span class="hljs-comment">## 3            home_ownership</span>
<span class="hljs-comment">## 4                   purpose</span>
<span class="hljs-comment">## 5                addr_state</span>
<span class="hljs-comment">## 6 verification_status_joint</span>
<span class="hljs-comment">## 7                    target</span></code></pre>
<p>Agora vamos transformá-las em factor e utilizar o comando droplevels para que categorias não utilizadas sejam removidas.</p>
<pre class="code"><code class="hljs">data_cleaned = 
   data_cleaned %&gt;% 
   <span class="hljs-title function_">mutate</span>(<span class="hljs-title function_">across</span>(
      .cols = <span class="hljs-title function_">c</span>(target, emp_length, term, home_ownership, purpose, addr_state, verification_status_joint),
      .fns = <span class="hljs-keyword">as</span>.factor)) %&gt;% 
   <span class="hljs-title function_">droplevels</span>()</code></pre>
<h2 id="analise-de-variaveis-numericas">Análise de variáveis numéricas</h2>
<p>Uma vez analisadas as variáveis categóricas faremos o mesmo processo com as variáveis numéricas.</p>
<pre class="code"><code class="hljs">data_cleaned %&gt;% 
   <span class="hljs-title function_">select_if</span>(<span class="hljs-keyword">is</span>.numeric) %&gt;% 
   <span class="hljs-title function_">names</span>() %&gt;% 
   reshape2::<span class="hljs-title function_">melt</span>()</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">##                          value</span>
<span class="hljs-comment">## 1                    loan_amnt</span>
<span class="hljs-comment">## 2                  funded_amnt</span>
<span class="hljs-comment">## 3              funded_amnt_inv</span>
<span class="hljs-comment">## 4                     int_rate</span>
<span class="hljs-comment">## 5                  installment</span>
<span class="hljs-comment">## 6                   annual_inc</span>
<span class="hljs-comment">## 7                          dti</span>
<span class="hljs-comment">## 8                  delinq_2yrs</span>
<span class="hljs-comment">## 9               inq_last_6mths</span>
<span class="hljs-comment">## 10      mths_since_last_delinq</span>
<span class="hljs-comment">## 11      mths_since_last_record</span>
<span class="hljs-comment">## 12                    open_acc</span>
<span class="hljs-comment">## 13                     pub_rec</span>
<span class="hljs-comment">## 14                   revol_bal</span>
<span class="hljs-comment">## 15                  revol_util</span>
<span class="hljs-comment">## 16                   total_acc</span>
<span class="hljs-comment">## 17                   out_prncp</span>
<span class="hljs-comment">## 18               out_prncp_inv</span>
<span class="hljs-comment">## 19                 total_pymnt</span>
<span class="hljs-comment">## 20             total_pymnt_inv</span>
<span class="hljs-comment">## 21             total_rec_prncp</span>
<span class="hljs-comment">## 22               total_rec_int</span>
<span class="hljs-comment">## 23          total_rec_late_fee</span>
<span class="hljs-comment">## 24                  recoveries</span>
<span class="hljs-comment">## 25     collection_recovery_fee</span>
<span class="hljs-comment">## 26             last_pymnt_amnt</span>
<span class="hljs-comment">## 27  collections_12_mths_ex_med</span>
<span class="hljs-comment">## 28 mths_since_last_major_derog</span>
<span class="hljs-comment">## 29                 policy_code</span>
<span class="hljs-comment">## 30            annual_inc_joint</span>
<span class="hljs-comment">## 31                   dti_joint</span>
<span class="hljs-comment">## 32              acc_now_delinq</span>
<span class="hljs-comment">## 33                tot_coll_amt</span>
<span class="hljs-comment">## 34                 tot_cur_bal</span>
<span class="hljs-comment">## 35                 open_acc_6m</span>
<span class="hljs-comment">## 36                  open_il_6m</span>
<span class="hljs-comment">## 37                 open_il_12m</span>
<span class="hljs-comment">## 38                 open_il_24m</span>
<span class="hljs-comment">## 39          mths_since_rcnt_il</span>
<span class="hljs-comment">## 40                total_bal_il</span>
<span class="hljs-comment">## 41                     il_util</span>
<span class="hljs-comment">## 42                 open_rv_12m</span>
<span class="hljs-comment">## 43                 open_rv_24m</span>
<span class="hljs-comment">## 44                  max_bal_bc</span>
<span class="hljs-comment">## 45                    all_util</span>
<span class="hljs-comment">## 46            total_rev_hi_lim</span>
<span class="hljs-comment">## 47                      inq_fi</span>
<span class="hljs-comment">## 48                 total_cu_tl</span>
<span class="hljs-comment">## 49                inq_last_12m</span></code></pre>
<p>Como podemos ver são 49 variáveis numéricas na base de dados e para não alongar ainda mais este texto, vou resumir o trabalho que fiz nos bastidores. Seguindo o exemplo anterior eu separei as variáveis numéricas em dois grupos:</p>
<h3 id="grupo-1-variaveis-que-mantidas-como-estao">Grupo 1 — Variáveis que mantidas como estão</h3>
<p>As variáveis mantidas apresentam valores que podem auxilar o modelo na tarefa de predição.</p>
<pre class="code"><code class="hljs"><span class="hljs-comment"># number of open credit lines in the borrower&#x27;s credit file.</span>
<span class="hljs-comment"># data_cleaned %&gt;% tabyl(open_acc) %&gt;% adorn_pct_formatting() %&gt;% arrange(desc(n))</span></code></pre>
<pre class="code"><code class="hljs"># number of open trades <span class="hljs-keyword">in</span> last <span class="hljs-number">6</span> months
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(open_acc_6m) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># number of negative public records (like loans that won´t granted)
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(pub_rec) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">The</span> number of months since the last public record.
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(mths_since_last_record) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(mths_since_rcnt_il) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(mths_since_last_major_derog) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># total collection amounts ever owed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(tot_coll_amt) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># total current balance of all accounts
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(tot_cur_bal) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Total</span> current balance of all installment accounts
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(total_bal_il) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Number</span> of finance trades
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(total_cu_tl) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Number</span> of collections (recoveries) <span class="hljs-keyword">in</span> <span class="hljs-number">12</span> months excluding medical collections
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(collections_12_mths_ex_med) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Number</span> of currently active installment trades
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(open_il_6m) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Number</span> of installment accounts opened <span class="hljs-keyword">in</span> past <span class="hljs-number">12</span> months
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(open_il_12m) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Number</span> of installment accounts opened <span class="hljs-keyword">in</span> past <span class="hljs-number">24</span> months
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(open_il_24m) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Number</span> of revolving trades opened <span class="hljs-keyword">in</span> past <span class="hljs-number">12</span> months
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(open_rv_12m) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Number</span> of revolving trades opened <span class="hljs-keyword">in</span> past <span class="hljs-number">24</span> months
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(open_rv_24m) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># balance to credit limit <span class="hljs-keyword">on</span> all trades
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(all_util) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">The</span> number of accounts <span class="hljs-keyword">on</span> which the borrower <span class="hljs-keyword">is</span> now delinquent.
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(acc_now_delinq) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Ratio</span> of: total current balance to high credit / credit limit <span class="hljs-keyword">on</span> all installment acct
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(il_util) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Maximum</span> current balance owed <span class="hljs-keyword">on</span> all revolving accounts
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(max_bal_bc) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<blockquote>
<p>Obs: Como estas variáveis podem possuir muitos valores eu as mantive comentadas para evitar processamento e output desnecessários</p>
</blockquote>
<p>Para estas variáveis ainda é necessário um segundo passo! Muitas possuem valores em branco o que não é permitido em random forests e por isso é necessário transformar os valores nulos em zero.</p>
<pre class="code"><code class="hljs">data_cleaned = 
   data_cleaned %&gt;% 
   <span class="hljs-title function_">mutate</span>(
      open_acc = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(open_acc), <span class="hljs-number">0</span>, open_acc),
      open_acc_6m = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(open_acc_6m), <span class="hljs-number">0</span>, open_acc_6m),
      pub_rec = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(pub_rec), <span class="hljs-number">0</span>, pub_rec),
      mths_since_last_record = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(mths_since_last_record), <span class="hljs-number">0</span>, mths_since_last_record),
      mths_since_rcnt_il = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(mths_since_rcnt_il), <span class="hljs-number">0</span>, mths_since_rcnt_il),
      mths_since_last_major_derog = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(mths_since_last_major_derog), <span class="hljs-number">0</span>, mths_since_last_major_derog),
      tot_coll_amt = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(tot_coll_amt), <span class="hljs-number">0</span>, tot_coll_amt),
      tot_cur_bal = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(tot_cur_bal), <span class="hljs-number">0</span>, tot_cur_bal),
      total_bal_il = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(total_bal_il), <span class="hljs-number">0</span>, total_bal_il),
      total_cu_tl = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(total_cu_tl), <span class="hljs-number">0</span>, total_cu_tl),
      collections_12_mths_ex_med = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(collections_12_mths_ex_med), <span class="hljs-number">0</span>, collections_12_mths_ex_med),
      open_il_6m = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(open_il_6m), <span class="hljs-number">0</span>, open_il_6m),
      open_il_12m = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(open_il_12m), <span class="hljs-number">0</span>, open_il_12m),
      open_il_24m = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(open_il_24m), <span class="hljs-number">0</span>, open_il_24m),
      open_rv_12m = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(open_rv_12m), <span class="hljs-number">0</span>, open_rv_12m),
      open_rv_24m = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(open_rv_24m), <span class="hljs-number">0</span>, open_rv_24m),
      all_util = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(all_util), <span class="hljs-number">0</span>, all_util),
      acc_now_delinq = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(acc_now_delinq), <span class="hljs-number">0</span>, acc_now_delinq),
      il_util = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(il_util), <span class="hljs-number">0</span>, il_util),
      max_bal_bc = <span class="hljs-title function_">ifelse</span>(<span class="hljs-keyword">is</span>.<span class="hljs-title function_">na</span>(max_bal_bc), <span class="hljs-number">0</span>, max_bal_bc)
   )</code></pre>
<h3 id="grupo-2-variaveis-que-serao-removidas-2">Grupo 2 — Variáveis que serão removidas</h3>
<p>Estas variáveis possuem valores que não contribuem para a análise por serem esparsos ou por se referirem a passos do processo de concessão do empréstimo que não impacta no processo de predição.</p>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Total</span> revolving high credit/credit limit - could be removed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(total_rev_hi_lim) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># values received, because <span class="hljs-keyword">this</span> variable <span class="hljs-keyword">is</span> used after the loan aproval, could be removed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(total_pymnt) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(total_pymnt_inv) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># total interest received, because <span class="hljs-keyword">this</span> variable <span class="hljs-keyword">is</span> used after the loan aproval, could be removed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(total_rec_int) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Late</span> fees received to date, because <span class="hljs-keyword">this</span> variable <span class="hljs-keyword">is</span> used after the loan aproval, could be removed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(total_rec_late_fee) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Principal</span> received to date, because <span class="hljs-keyword">this</span> variable <span class="hljs-keyword">is</span> used after the loan aproval, could be removed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(total_rec_prncp) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Remaining</span> outstanding principal <span class="hljs-keyword">for</span> total amount funded, could be removed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(out_prncp) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Remaining</span> outstanding principal <span class="hljs-keyword">for</span> portion of total amount funded by investors, could be removed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(out_prncp_inv) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># values charged <span class="hljs-keyword">when</span> the bank recover a loan that whasn´t payed, could be removed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(recoveries) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(collection_recovery_fee) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Last</span> total payment amount received, could be removed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(last_pymnt_amnt) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment"># that variable have the save value for all dataset, could be removed</span>
<span class="hljs-comment"># data_cleaned %&gt;% tabyl(policy_code) %&gt;% adorn_pct_formatting() %&gt;% arrange(desc(n))</span></code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">The</span> number of inquiries <span class="hljs-keyword">in</span> past <span class="hljs-number">6</span> months (excluding auto and mortgage inquiries)
# because are a lack of information about that varible it will be removed
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(inq_last_6mths) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(inq_fi) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))
# data_cleaned %&gt;% <span class="hljs-title function_">tabyl</span>(inq_last_12m) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))</code></pre>
<blockquote>
<p>Obs: Como estas variáveis podem possuir muitos valores eu as mantive comentadas para evitar processamento e output desnecessários</p>
</blockquote>
<p>Para fazer a remoção delas utilizei o comando abaixo</p>
<pre class="code"><code class="hljs">data_cleaned = 
   data_cleaned %&gt;%
   <span class="hljs-title function_">select</span>(<span class="hljs-title function_">everything</span>(), 
          -funded_amnt, -funded_amnt_inv, -installment, -dti, -inq_last_6mths, -mths_since_last_delinq, -total_rev_hi_lim, -total_pymnt, -total_pymnt_inv, -total_rec_int, -total_rec_prncp, -total_rec_late_fee, -total_rec_late_fee, -out_prncp, -out_prncp_inv, -recoveries, -collection_recovery_fee, -dti_joint, -last_pymnt_amnt, -policy_code, -annual_inc_joint, -inq_fi, -inq_last_12m
   ) %&gt;%
   <span class="hljs-title function_">drop_na</span>()</code></pre>
<h2 id="exploracao-dos-dados">Exploração dos dados</h2>
<p>Vamos verificar algumas informações da base final, como a distribuição dos empréstimos de acordo com a variável target:</p>
<pre class="code"><code class="hljs"><span class="hljs-title function_">ggplot</span>(
   data_cleaned %&gt;% <span class="hljs-title function_">group_by</span>(target) %&gt;% <span class="hljs-title function_">summarise</span>(n = <span class="hljs-title function_">n</span>()), 
   <span class="hljs-title function_">aes</span>(x = <span class="hljs-title function_">reorder</span>(target, (n)), y = n, fill = target)) +
<span class="hljs-title function_">geom_bar</span>(stat = <span class="hljs-string">&quot;identity&quot;</span>) +
<span class="hljs-title function_">geom_label</span>(<span class="hljs-title function_">aes</span>(label = n), hjust = <span class="hljs-number">1.2</span>, size = <span class="hljs-number">3</span>) +
<span class="hljs-title function_">scale_colour_viridis_d</span>() +
<span class="hljs-title function_">coord_flip</span>() +
<span class="hljs-title function_">labs</span>(title = <span class="hljs-string">&#x27;Volume per loan status&#x27;</span>, x = <span class="hljs-string">&quot;Loan Status&quot;</span>, y = <span class="hljs-string">&quot;Volume&quot;</span>) +
<span class="hljs-title function_">theme</span>(legend.title = <span class="hljs-title function_">element_blank</span>(),
      panel.border = <span class="hljs-title function_">element_rect</span>(NA),
      panel.grid = <span class="hljs-title function_">element_blank</span>(),
      panel.background = <span class="hljs-title function_">element_rect</span>(<span class="hljs-string">&quot;white&quot;</span>),
      legend.position = <span class="hljs-string">&quot;none&quot;</span>,
      axis.text.x = <span class="hljs-title function_">element_text</span>(angle = <span class="hljs-number">90</span>),
      strip.background =  <span class="hljs-title function_">element_rect</span>(colour=<span class="hljs-string">&quot;black&quot;</span>, size = <span class="hljs-number">0.5</span>),
      strip.text = <span class="hljs-title function_">element_text</span>(size = <span class="hljs-number">10</span>, color=<span class="hljs-string">&quot;black&quot;</span>, face = <span class="hljs-string">&quot;bold&quot;</span>))</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-z8KT26FOLL5Xd%2Fcontent%2F62eb55f7aec6a881.png?alt=media&amp;token=9bb31100-5210-422f-802d-30482edc61c2" alt="" loading="lazy" decoding="async">
<p>Podemos ver que 66 mil empréstimos (~24% do total) tiveram algum problema com o pagamento.</p>
<p>Dentre as variáveis categóricas preservadas temos a que indica o propósito do empréstimo. Ela pode ajudar a entender quais motivadores são mais propensos a eventuais problemas com pagamento.</p>
<pre class="code"><code class="hljs"><span class="hljs-title function_">ggplot</span>(
   data_cleaned %&gt;% 
      <span class="hljs-title function_">group_by</span>(target, purpose) %&gt;% 
      <span class="hljs-title function_">summarise</span>(n = <span class="hljs-title function_">n</span>()), 
   <span class="hljs-title function_">aes</span>(x = <span class="hljs-title function_">reorder</span>(purpose, (n)), y = n, fill = target)) +
   <span class="hljs-title function_">geom_bar</span>(stat = <span class="hljs-string">&quot;identity&quot;</span>) +
   <span class="hljs-title function_">geom_label</span>(<span class="hljs-title function_">aes</span>(label = n), hjust = <span class="hljs-number">1.2</span>, size = <span class="hljs-number">3</span>) +
   <span class="hljs-title function_">scale_colour_viridis_d</span>() +
   <span class="hljs-title function_">coord_flip</span>() +
   <span class="hljs-title function_">labs</span>(title = <span class="hljs-string">&#x27;Loans per purpose&#x27;</span>, x = <span class="hljs-string">&quot;Purpose&quot;</span>, y = <span class="hljs-string">&quot;Volume&quot;</span>) +
   <span class="hljs-title function_">theme</span>(legend.title = <span class="hljs-title function_">element_blank</span>(),
         panel.border = <span class="hljs-title function_">element_rect</span>(NA),
         panel.grid = <span class="hljs-title function_">element_blank</span>(),
         panel.background = <span class="hljs-title function_">element_rect</span>(<span class="hljs-string">&quot;white&quot;</span>),
         legend.position = <span class="hljs-string">&quot;none&quot;</span>,
         axis.text.x = <span class="hljs-title function_">element_text</span>(angle = <span class="hljs-number">90</span>),
         strip.background =  <span class="hljs-title function_">element_rect</span>(colour=<span class="hljs-string">&quot;black&quot;</span>, size = <span class="hljs-number">0.5</span>),
         strip.text = <span class="hljs-title function_">element_text</span>(size = <span class="hljs-number">10</span>, color=<span class="hljs-string">&quot;black&quot;</span>, face = <span class="hljs-string">&quot;bold&quot;</span>))</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-z8KT26FOLL5Xd%2Fcontent%2F1181034caf27cd48.png?alt=media&amp;token=08577761-6031-4d81-bfcb-86fb5ac8b98c" alt="" loading="lazy" decoding="async">
<p>Como podemos observar, empréstimos com o propósito <em><strong>debt_consolidation</strong></em> apresenta a maior incidência de empréstimos com problemas de pagamento.</p>
<h2 id="preparacao-dos-dados-para-o-modelo">Preparação dos dados para o modelo</h2>
<p>Uma vez que os dados foram tratados e “limpos” podemos prepará-los para executarmos nossa random forest. Este passo embora simples, é fundamental para continuarmos. Ele pode ser separado em 3 etapas:</p>
<ol>
<li>Separação dos dados de treino e teste: para isso eu utilizei o comando sample.split do pacote caTools. Ele irá criar uma lista de valores booleanos para cada empréstimo de nossa base. Aleatoriamente irá indicar qual será deles será utilizado em nossa base de treino, que terá 80% dos dados. Ela irá utilizar como base a coluna target, para garantir que tenha uma distribuição uniforme para teste e treino</li>
<li>Criação da base de treino: utilizando a lista criada anteriormente faremos uma cópia dos dados de treino para um dataset separado</li>
<li>Criação da base de teste: esta base será utilizada para validar o modelo que criamos</li>
</ol>
<pre class="code"><code class="hljs">train_sample = caTools::sample.<span class="hljs-title function_">split</span>(
   data_cleaned$target, 
   <span class="hljs-title class_">SplitRatio</span> = .<span class="hljs-number">80</span>)</code></pre>
<pre class="code"><code class="hljs">train_data <span class="hljs-operator">=</span> subset<span class="hljs-punctuation">(</span>data_cleaned<span class="hljs-punctuation">,</span> train_sample <span class="hljs-operator">==</span> <span class="hljs-built_in">T</span><span class="hljs-punctuation">)</span>
test_data  <span class="hljs-operator">=</span> subset<span class="hljs-punctuation">(</span>data_cleaned<span class="hljs-punctuation">,</span> train_sample <span class="hljs-operator">==</span> <span class="hljs-built_in">F</span><span class="hljs-punctuation">)</span></code></pre>
<p>O próximo passo é avaliar a base de dados para identifica quais são os melhores parâmetros para nosso modelo. Para isso utilizei o comando tuneRF do pacote randonForests. Ele irá avaliar a taxa de acerto de diferentes combinações das variáveis de nossa base até encontrar aquela que apresenta a melhor taxa.</p>
<pre class="code"><code class="hljs">mtry <span class="hljs-operator">=</span> 
   randomForest<span class="hljs-operator">::</span>tuneRF<span class="hljs-punctuation">(</span>
      <span class="hljs-comment">#list of variables that will be used, in this case all but target</span>
      train_data <span class="hljs-operator">%&gt;%</span> select<span class="hljs-punctuation">(</span><span class="hljs-operator">-</span>target<span class="hljs-punctuation">)</span><span class="hljs-punctuation">,</span> 
      <span class="hljs-comment"># the information that we want to predict</span>
      train_data<span class="hljs-operator">$</span>targe<span class="hljs-punctuation">,</span> 
      <span class="hljs-comment"># number of trees that should be evaluated </span>
      ntreeTry<span class="hljs-operator">=</span><span class="hljs-number">300</span><span class="hljs-punctuation">,</span>
      stepFactor<span class="hljs-operator">=</span><span class="hljs-number">1.5</span><span class="hljs-punctuation">,</span>
      improve<span class="hljs-operator">=</span><span class="hljs-number">0.01</span><span class="hljs-punctuation">)</span></code></pre>
<pre class="code"><code class="hljs"><span class="hljs-meta">## mtry = 5  OOB <span class="hljs-keyword">error</span> = 23.89% </span>
<span class="hljs-meta">## Searching left ...</span>
<span class="hljs-meta">## mtry = 4     OOB <span class="hljs-keyword">error</span> = 23.97% </span>
<span class="hljs-meta">## -0.003454528 0.01 </span>
<span class="hljs-meta">## Searching right ...</span>
<span class="hljs-meta">## mtry = 7     OOB <span class="hljs-keyword">error</span> = 23.93% </span>
<span class="hljs-meta">## -0.001698635 0.01</span></code></pre>
<p>Agora podemos iniciar a execução de nosso modelo. Não vou entrar em detalhes aqui sobre random forests, por isso deixo o link para um outro texto que escrevi sobre o tema e falo com um pouco mais de detalhes no <a href="https://medium.com/@marcosmhs/random-forests-101-com-r-d5c1821dc445" target="_blank" rel="noopener">Blog Medium</a></p>
<pre class="code"><code class="hljs">model <span class="hljs-operator">=</span> 
   randomForest<span class="hljs-operator">::</span>randomForest<span class="hljs-punctuation">(</span>
      <span class="hljs-comment"># a fórmula da árvore, a informação de ataque cardíaco (stroke) em função de todas as variáveis de nossa base de dados</span>
      formula <span class="hljs-operator">=</span> target <span class="hljs-operator">~</span> .<span class="hljs-punctuation">,</span>
      <span class="hljs-comment"># a base de treino com xxxx registros</span>
      data <span class="hljs-operator">=</span> train_data<span class="hljs-punctuation">,</span> 
      <span class="hljs-comment"># quantidade de colunas que serão utilizadas em cada árvore</span>
      mtry <span class="hljs-operator">=</span> <span class="hljs-number">5</span><span class="hljs-punctuation">,</span>
      <span class="hljs-comment"># quantidade de árvores que devem ser criadas pelo algorítmo </span>
      ntree<span class="hljs-operator">=</span><span class="hljs-number">300</span><span class="hljs-punctuation">)</span></code></pre>
<p>Vamos verificar quais foram as variáveis que geraram a menor quantidade de erros durante a execução do modelo.</p>
<pre class="code"><code class="hljs">randomForest<span class="hljs-operator">::</span>varImpPlot<span class="hljs-punctuation">(</span>model<span class="hljs-punctuation">,</span> sort <span class="hljs-operator">=</span> <span class="hljs-built_in">T</span><span class="hljs-punctuation">,</span> <span class="hljs-punctuation">)</span></code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-z8KT26FOLL5Xd%2Fcontent%2Fcac5d8f543f96c65.png?alt=media&amp;token=c86ec146-a7bc-4923-8103-b94f93ba3192" alt="" loading="lazy" decoding="async">
<p>Podemos ver que as variáveis addr_state e int_rate foram as mais relevantes, enquanto open_li_24 e open_li_12 não geraram impacto sobre o resultado.</p>
<h2 id="conferindo-o-resultado">Conferindo o resultado</h2>
<p>O próximo passo agora é adicionar em nossa base de teste uma coluna com o resultado predito pelo nosso modelo, para que possamos compará-la com o resultado real.</p>
<pre class="code"><code class="hljs">test_data$rf_prediction = 
    predict(model, test_data, <span class="hljs-built_in">type</span> = “<span class="hljs-keyword">class</span>”)</code></pre>
<p>Vamos criar uma matriz de confusão para visualizarmos o resultado predito</p>
<pre class="code"><code class="hljs">confusion_table = 
   <span class="hljs-keyword">as</span>.data.<span class="hljs-title function_">frame</span>(
      <span class="hljs-title function_">table</span>(
         real = test_data$loan_status, 
         predicted = test_data$rf_prediction)
   ) %&gt;%
   <span class="hljs-title function_">mutate</span>(`*` = <span class="hljs-title function_">ifelse</span>(real == predicted, <span class="hljs-string">&#x27;*&#x27;</span>, <span class="hljs-string">&#x27;&#x27;</span>)) %&gt;%
   <span class="hljs-title function_">left_join</span>(test_data %&gt;%
                <span class="hljs-title function_">group_by</span>(real = loan_status) %&gt;%
                <span class="hljs-title function_">summarise</span>(n_real = <span class="hljs-title function_">n</span>()), by=<span class="hljs-string">&quot;real&quot;</span>) %&gt;%
   <span class="hljs-title function_">arrange</span>(real)</code></pre>
<p>Agora vejamos o resultado:</p>
<pre class="code"><code class="hljs">confusion_table %&gt;%
   <span class="hljs-title function_">filter</span>(`*` == <span class="hljs-string">&#x27;*&#x27;</span>) %&gt;%
   <span class="hljs-title function_">mutate</span>(acuracy = <span class="hljs-title function_">ifelse</span>(
      <span class="hljs-title class_">Freq</span> == <span class="hljs-number">0</span>, 
      <span class="hljs-number">0</span>, 
      <span class="hljs-title function_">round</span>((<span class="hljs-title class_">Freq</span> / n_real) * <span class="hljs-number">100</span>, <span class="hljs-number">2</span>))) %&gt;%
   <span class="hljs-title function_">select</span>(real, <span class="hljs-title class_">Freq</span>, n_real, acuracy)</code></pre>
<pre class="code"><code class="hljs">         real   <span class="hljs-title class_">Freq</span>  n_real  acuracy
<span class="hljs-number">1</span>  <span class="hljs-title class_">Bad</span> borrow    <span class="hljs-number">675</span>   <span class="hljs-number">13321</span>     <span class="hljs-number">5.07</span>
<span class="hljs-number">2</span> <span class="hljs-title class_">Good</span> borrow  <span class="hljs-number">41074</span>   <span class="hljs-number">41514</span>    <span class="hljs-number">98.94</span></code></pre>
<p>Vamos conferir a acurácia do modelo, ou seja, o percentual geral de acerto:</p>
<pre class="code"><code class="hljs">confusion_table %&gt;%
   <span class="hljs-title function_">mutate</span>(correct_prediction = <span class="hljs-title function_">ifelse</span>(
      real == predicted, 
      <span class="hljs-title class_">Freq</span>, 
      <span class="hljs-number">0</span>)) %&gt;%
   <span class="hljs-title function_">summarise</span>(total = <span class="hljs-title function_">sum</span>(<span class="hljs-title class_">Freq</span>),
             correct = <span class="hljs-title function_">sum</span>(correct_prediction)) %&gt;%
   <span class="hljs-title function_">mutate</span>(acuracy = correct / total)</code></pre>
<pre class="code"><code class="hljs">
<span class="hljs-comment">#  total  correct   accuracy</span>
<span class="hljs-comment">#1 54835    41749  0.7613568</span></code></pre>
<p>Combinando as duas informações podemos ver que de forma geral o modelo foi capaz de acertar 76% dos 54 mil empréstimos, porém ele erra mais ao tentar prever maus pagadores, apenas 5% dos empréstimos foram indicados corretamente. Já na previsão de bons pagadores, o modelo foi capaz de acertar ~99% de todos os empréstimos!</p>
<h2 id="conclusoes">Conclusões</h2>
<p>Vimos que o modelo possui uma acurácia interessante, sendo muito bom em dizer se a pessoa irá pagar o empréstimo até o final, mas apresenta algumas falhas ao prever aqueles que não irão pagá-lo.</p>
<p>Para encerrar, o que eu acho bacana em data science é que ela não se trata apenas de criar modelos matemáticos, existe um universo inteiro de análise de dados e compreensão do problema que se deseja resolver. Por exemplo neste caso, eu poderia chegar à conclusão de que uma regressão logística seria suficiente para resolver esta necessidade de prever se aquela pessoa irá ou não pagar seu empréstimo até o final.</p>
<p>Caso encontre alguma canelada ou um falha no código por favor entre em cotnato comigo através do e-mail <a href="mailto:marcosmhs@live.com">marcosmhs@live.com</a> e ficarei feliz em fazer os ajustes necessários e colocá-lo(a) como co-autor.</p>
]]></content:encoded>
  </item>
  <item>
    <title>Utilização de Keras para predição com dados estruturados</title>
    <link>https://www.marcosmhs.com.br/artigos/utilizacao-de-keras-para-predicao-com-dados-estruturados/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/utilizacao-de-keras-para-predicao-com-dados-estruturados/</guid>
    <pubDate>Sun, 31 Jul 2022 15:17:43 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>Python</category>
    <category>Keras</category>
    <description>Este exemplo demostra como realizar classificação de dados estruturados à partir de um arquivo CSV. As informações incluem dados numéricos e categóricos. Será…</description>
    <content:encoded><![CDATA[<figure><img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-bGrCK2cuKp04n%2Fcontent%2F37cb1f2f52eab271.jpg?alt=media&amp;token=855fe0ce-da02-45d6-bd77-0e4b136a6e73" alt="Deep Learning Book (Deep Learning Book)" loading="lazy" decoding="async"><figcaption>Deep Learning Book (Deep Learning Book)</figcaption></figure>
<p><strong>Introdução</strong></p>
<p>Este exemplo demostra como realizar classificação de dados estruturados à partir de um arquivo CSV. As informações incluem dados numéricos e categóricos. Será utilizada a biblioteca <a href="https://keras.io/" target="_blank" rel="noopener"><em><strong>Keras</strong></em></a> para o processamento das informações e normalização dos dados numéricos e transformação dos dados categóricos em vetores.</p>
<p><em>Para este exemplo é necessário o uso do</em> <em><strong>TensorFlow 2.5</strong></em> <em>ou superior</em></p>
<p><strong>O Dataset</strong></p>
<p><a href="https://archive.ics.uci.edu/ml/datasets/heart+Disease" target="_blank" rel="noopener">Os dados</a> são disponibilizados pelo <em>Cleveland Clinic Foundation for Heart Disease e</em>m um arquivo um arquivo CSV com 303 linhas, sendo que cada linha possui informações sobre um paciente (<strong>amostra</strong>). Utilizaremos estes dados para prevermos se um paciente teve ou não problema no coração.</p>
<p>Descrição das colunas</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-bGrCK2cuKp04n%2Fcontent%2Fa6862955a61cedad.png?alt=media&amp;token=4206a0a5-f7ec-4307-b89e-2766b85f1b0e" alt="" loading="lazy" decoding="async">
<pre class="code"><code class="hljs"><span class="hljs-keyword">import</span> tensorflow <span class="hljs-keyword">as</span> tf
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">from</span> tensorflow <span class="hljs-keyword">import</span> keras
<span class="hljs-keyword">from</span> tensorflow.keras <span class="hljs-keyword">import</span> layers</code></pre>
<pre class="code"><code class="hljs">dados = pd.<span class="hljs-title function_">read_csv</span>(“heart.csv<span class="hljs-string">&quot;)</span></code></pre>
<p>Rápida visualização da estrutura do <em>dataframe</em></p>
<pre class="code"><code class="hljs">dados.shape
dados.<span class="hljs-title function_">head</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-bGrCK2cuKp04n%2Fcontent%2F99a90af550ddeb2b.png?alt=media&amp;token=3361dc28-0051-43e4-9a6d-f3dc4d338ba1" alt="" loading="lazy" decoding="async">
<p>Separação dos dados em treino e teste</p>
<pre class="code"><code class="hljs">dados_treino = dados.<span class="hljs-title function_">sample</span>(frac=<span class="hljs-number">0.75</span>, random_state=<span class="hljs-number">1337</span>)
dados_teste = dados.<span class="hljs-title function_">drop</span>(dados_treino.index)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-built_in">print</span>(<span class="hljs-string">&quot;Usando %d amostras para treino e %d para testar a acurácia do modelo&quot;</span>% (<span class="hljs-built_in">len</span>(dados_treino), <span class="hljs-built_in">len</span>(dados_teste)))</code></pre>
<pre class="code"><code class="hljs">____</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-title class_">Usando</span> <span class="hljs-number">227</span> amostras para treino e <span class="hljs-number">76</span> para testar a acurácia <span class="hljs-keyword">do</span> modelo</code></pre>
<p>Para utilização do tensor flow é necessário transformar os <em>dataframes</em> de treino e teste me objetos do tipo <strong>tf.data.Dataset</strong>.</p>
<pre class="code"><code class="hljs">def <span class="hljs-title function_">dataframe_para_dataset</span>(df):
  df = df.<span class="hljs-title function_">copy</span>()
  # extrai apenas a variável Y (target)
  labels = df.<span class="hljs-title function_">pop</span>(<span class="hljs-string">&quot;target&quot;</span>)
  ds = tf.data.<span class="hljs-title class_">Dataset</span>.<span class="hljs-title function_">from_tensor_slices</span>((<span class="hljs-title function_">dict</span>(df), labels))
  ds = ds.<span class="hljs-title function_">shuffle</span>(buffer_size=<span class="hljs-title function_">len</span>(df))
  <span class="hljs-keyword">return</span> ds</code></pre>
<pre class="code"><code class="hljs">treino_ds = <span class="hljs-title function_">dataframe_para_dataset</span>(dados_treino)
teste_ds = <span class="hljs-title function_">dataframe_para_dataset</span>(dados_teste)</code></pre>
<p>Cada <em>Dataset</em> armazena um conjunto (<em>input e target</em>) onde <em>input</em> é a lista de variáveis utilizadas para predição e <em>target</em> armazena o valor 0 ou 1 da variável resposta (y)</p>
<p>Agora vamos agrupar os dados em lotes de 32 linhas, passo importante para o uso do tensor flow</p>
<pre class="code"><code class="hljs">treino_ds = treino_ds.<span class="hljs-title function_">batch</span>(<span class="hljs-number">32</span>)
teste_ds = teste_ds.<span class="hljs-title function_">batch</span>(<span class="hljs-number">32</span>)</code></pre>
<p><strong>Pré-processamento dos dados com Keras</strong></p>
<p>As variáveis abaixo são categóricas, porém estão armazenadas como números inteiros:</p>
<ul>
<li>sex</li>
<li>cp</li>
<li>fbs</li>
<li>restecg</li>
<li>exang</li>
<li>ca</li>
</ul>
<p>Precisamos transformar estas variáveis utilizando o método <em>one-hot encoding</em> onde cada valor único da variável se transforma em uma coluna binária indicando 1 para a existência daquele valor e 0 para sua ausência. Este método é o mesmo que a transformação de variáveis categóricas em variáveis dummy.</p>
<p>Neste caso faremos os seguintes passos:</p>
<p>- Utilizaremos o método <em>CategoryEncoding()</em>, que precisa saber a quantidade de valores únicos de cada variável.</p>
<p>- Em seguida utilizaremos o método <em>IntegerLookup()</em> que cria uma tabela de referência para os valores selecionados anteriormente.</p>
<p>Para este exemplo, nós seguiremos uma solução simples que lidará com os valores inteiros, por isso seguiremos com o método <em>IntegerLookup()</em></p>
<p>Também temos uma variável do tipo texto `thal`. Para ela usaremos o método <em>StringLookup()</em> para a criação das colunas de classificação</p>
<p>Por fim, temos as variáveis numéricas:</p>
<ul>
<li>age</li>
<li>trestbps</li>
<li>chol</li>
<li>thalach</li>
<li>oldpeak</li>
<li>slope</li>
</ul>
<p>Para elas utilizaremos o método <em>Normalization()</em> que fará a padronização dos valores em uma faixa entre 0 e 1</p>
<p>Abaixo definimos a criação de 2 métodos para o tratamento dos valores:</p>
<ul>
<li><strong>normalizacao_variavel_numericas</strong> responsável pela normalização dos valores numéricos</li>
<li><strong>transformacao_variavel_categorica</strong> responsável pela aplicação do método <em>one-hot endoding</em> nas categóricas, utilizando o parâmetro string para indicar se a variável em questão é texto ou numérica</li>
</ul>
<pre class="code"><code class="hljs"><span class="hljs-keyword">from</span> tensorflow.keras.layers <span class="hljs-keyword">import</span> IntegerLookup
<span class="hljs-keyword">from</span> tensorflow.keras.layers <span class="hljs-keyword">import</span> Normalization
<span class="hljs-keyword">from</span> tensorflow.keras.layers <span class="hljs-keyword">import</span> StringLookup</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-keyword">def</span> <span class="hljs-title function_">normalizacao_variavel_numericas</span>(<span class="hljs-params">variavel, nome, ds</span>):
  normalizer = Normalization()</code></pre>
<pre class="code"><code class="hljs">  <span class="hljs-comment"># Separa apenas a variável que será normalizada</span>
  variavel_ds = ds.<span class="hljs-built_in">map</span>(<span class="hljs-keyword">lambda</span> x, y: x[nome])
  variavel_ds = variavel_ds.<span class="hljs-built_in">map</span>(<span class="hljs-keyword">lambda</span> x: tf.expand_dims(x, -<span class="hljs-number">1</span>))</code></pre>
<pre class="code"><code class="hljs">  <span class="hljs-comment"># Calcula o índice dos dados para normalização</span>
  normalizer.adapt<span class="hljs-punctuation">(</span>variavel_ds<span class="hljs-punctuation">)</span></code></pre>
<pre class="code"><code class="hljs">  # <span class="hljs-title class_">Normaliza</span>ção da variável e retorno
  variavel_normalizada = <span class="hljs-title function_">normalizer</span>(variavel)
  <span class="hljs-keyword">return</span> variavel_normalizada</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-keyword">def</span> <span class="hljs-title function_">transformacao_variavel_categorica</span>(<span class="hljs-params">variavel, nome, ds, string</span>):
  <span class="hljs-comment"># Separa a classe de acordo com o tipo da variável</span>
  <span class="hljs-keyword">if</span> (string):
    lookup_class = StringLookup
  <span class="hljs-keyword">else</span>:
    lookup_class = IntegerLookup
    
  <span class="hljs-comment"># cria a tabela de referência que irá transformar as strings em íncides númericos</span>
  tabela_referencia = lookup_class(output_mode=<span class="hljs-string">&quot;binary&quot;</span>)</code></pre>
<pre class="code"><code class="hljs">  <span class="hljs-comment"># Separa apenas a coluna alvo do dataset</span>
  variavel_ds = ds.<span class="hljs-built_in">map</span>(<span class="hljs-keyword">lambda</span> x, y: x[nome])
  variavel_ds = variavel_ds.<span class="hljs-built_in">map</span>(<span class="hljs-keyword">lambda</span> x: tf.expand_dims(x, -<span class="hljs-number">1</span>))</code></pre>
<pre class="code"><code class="hljs">  <span class="hljs-comment"># Obtem a lista de valores únicos e atribui para cada um um valor numérico</span>
  tabela_referencia.adapt<span class="hljs-punctuation">(</span>variavel_ds<span class="hljs-punctuation">)</span></code></pre>
<pre class="code"><code class="hljs">  # transforma o valor string em valor <span class="hljs-built_in">num</span>érico
  encoded_feature = <span class="hljs-title function_">tabela_referencia</span>(variavel)
  <span class="hljs-keyword">return</span> encoded_feature</code></pre>
<h2 id="construcao-do-modelo"><strong>Construção do modelo</strong></h2>
<p>Primeiramente iremos construir a estrutura de entrada, ou seja, quais variáveis devem ser informadas e qual o tipo de cada uma.</p>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Categorical</span> features encoded <span class="hljs-keyword">as</span> integers
sex      = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;sex&quot;</span>    , dtype=<span class="hljs-string">&quot;int64&quot;</span>)
cp       = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;cp&quot;</span>     , dtype=<span class="hljs-string">&quot;int64&quot;</span>)
fbs      = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;fbs&quot;</span>    , dtype=<span class="hljs-string">&quot;int64&quot;</span>)
restecg  = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;restecg&quot;</span>, dtype=<span class="hljs-string">&quot;int64&quot;</span>)
exang    = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;exang&quot;</span>  , dtype=<span class="hljs-string">&quot;int64&quot;</span>)
ca       = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;ca&quot;</span>     , dtype=<span class="hljs-string">&quot;int64&quot;</span>)</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Categorical</span> feature encoded <span class="hljs-keyword">as</span> string
thal     = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;thal&quot;</span>   , dtype=<span class="hljs-string">&quot;string&quot;</span>)</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Numerical</span> features
age      = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;age&quot;</span>)
trestbps = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;trestbps&quot;</span>)
chol     = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;chol&quot;</span>)
thalach  = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;thalach&quot;</span>)
oldpeak  = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;oldpeak&quot;</span>)
slope    = keras.<span class="hljs-title class_">Input</span>(shape=(<span class="hljs-number">1</span>,), name=<span class="hljs-string">&quot;slope&quot;</span>)</code></pre>
<pre class="code"><code class="hljs">all_inputs = [sex, <span class="hljs-built_in">cp</span>, fbs, restecg, exang, ca, thal, age, trestbps, chol, thalach, oldpeak, slope,]</code></pre>
<p>Agora indicaremos ao modelo que topo de <strong>transformação</strong> deve ser feita com os dados que forem inseridos.</p>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Integer</span> categorical features
sex_encoded      = <span class="hljs-title function_">transformacao_variavel_categorica</span>(sex, <span class="hljs-string">&quot;sex&quot;</span>, treino_ds, <span class="hljs-title class_">False</span>)
cp_encoded       = <span class="hljs-title function_">transformacao_variavel_categorica</span>(cp, <span class="hljs-string">&quot;cp&quot;</span>, treino_ds, <span class="hljs-title class_">False</span>)
fbs_encoded      = <span class="hljs-title function_">transformacao_variavel_categorica</span>(fbs, <span class="hljs-string">&quot;fbs&quot;</span>, treino_ds, <span class="hljs-title class_">False</span>)
restecg_encoded  = <span class="hljs-title function_">transformacao_variavel_categorica</span>(restecg, <span class="hljs-string">&quot;restecg&quot;</span>, treino_ds, <span class="hljs-title class_">False</span>)
exang_encoded    = <span class="hljs-title function_">transformacao_variavel_categorica</span>(exang, <span class="hljs-string">&quot;exang&quot;</span>, treino_ds, <span class="hljs-title class_">False</span>)
ca_encoded       = <span class="hljs-title function_">transformacao_variavel_categorica</span>(ca, <span class="hljs-string">&quot;ca&quot;</span>, treino_ds, <span class="hljs-title class_">False</span>)</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">String</span> categorical features
thal_encoded     = <span class="hljs-title function_">transformacao_variavel_categorica</span>(thal, <span class="hljs-string">&quot;thal&quot;</span>, treino_ds, <span class="hljs-title class_">True</span>)</code></pre>
<pre class="code"><code class="hljs"># <span class="hljs-title class_">Numerical</span> features
age_encoded      = <span class="hljs-title function_">normalizacao_variavel_numericas</span>(age, <span class="hljs-string">&quot;age&quot;</span>, treino_ds)
trestbps_encoded = <span class="hljs-title function_">normalizacao_variavel_numericas</span>(trestbps, <span class="hljs-string">&quot;trestbps&quot;</span>, treino_ds)
chol_encoded     = <span class="hljs-title function_">normalizacao_variavel_numericas</span>(chol, <span class="hljs-string">&quot;chol&quot;</span>, treino_ds)
thalach_encoded  = <span class="hljs-title function_">normalizacao_variavel_numericas</span>(thalach, <span class="hljs-string">&quot;thalach&quot;</span>, treino_ds)
oldpeak_encoded  = <span class="hljs-title function_">normalizacao_variavel_numericas</span>(oldpeak, <span class="hljs-string">&quot;oldpeak&quot;</span>, treino_ds)
slope_encoded    = <span class="hljs-title function_">normalizacao_variavel_numericas</span>(slope, <span class="hljs-string">&quot;slope&quot;</span>, treino_ds)</code></pre>
<pre class="code"><code class="hljs">all_features = layers.<span class="hljs-title function_">concatenate</span>([
    sex_encoded,
    cp_encoded,
    fbs_encoded,
    restecg_encoded,
    exang_encoded,
    slope_encoded,
    ca_encoded,
    thal_encoded,
    age_encoded,
    trestbps_encoded,
    chol_encoded,
    thalach_encoded,
    oldpeak_encoded,
])</code></pre>
<p>Por fim vamos configurar a rede neural, ela terá apenas 2 camadas, uma de entrada e uma de saída.</p>
<p>- <strong>camada de entrada</strong>: Ela irá receber dados em lotes de 32 em 32 registros, seguindo o mesmo padrão que adotamos para a separação dos lotes de dados de treino e teste. Para a rede indicar se um neurônio deve ou não ser ativado utilizaremos a função `relu`, uma das mais comuns em redes neurais.</p>
<p>- <strong>cama de saída</strong>: a camada de saída irá trabalhar com apenas uma unidade de saída, neste caso o % de ocorrer ou não o problema no coração e para isso usaremos a função de ativação `sigmoide` que tenta “empurrar” o valor predito para os extemos possíveis da variável Y, neste caso o mais perto possível de 0 ou 1.</p>
<p>Para ler mais sobre função de ativação recomendo <a href="https://www.deeplearningbook.com.br/funcao-de-ativacao/#:~:text=ReLU&amp;text=ReLU%20%C3%A9%20a%20fun%C3%A7%C3%A3o%20de,neur%C3%B4nios%20ativados%20pela%20fun%C3%A7%C3%A3o%20ReLU." target="_blank" rel="noopener">Deep learning Book</a></p>
<pre class="code"><code class="hljs">camada_entrada = layers.<span class="hljs-title class_">Dense</span>(units=<span class="hljs-number">32</span>, activation=<span class="hljs-string">&quot;relu&quot;</span>)(all_features)
camada_entrada = layers.<span class="hljs-title class_">Dropout</span>(<span class="hljs-number">0.5</span>)(camada_entrada)</code></pre>
<pre class="code"><code class="hljs">camada_saida = layers.<span class="hljs-title class_">Dense</span>(units=<span class="hljs-number">1</span>, activation=<span class="hljs-string">&quot;sigmoid&quot;</span>)(camada_entrada)</code></pre>
<pre class="code"><code class="hljs">modelo = keras.<span class="hljs-title class_">Model</span>(all_inputs, camada_saida)</code></pre>
<pre class="code"><code class="hljs">modelo.<span class="hljs-built_in">compile</span>(<span class="hljs-string">&quot;adam&quot;</span>, <span class="hljs-string">&quot;binary_crossentropy&quot;</span>, metrics=[<span class="hljs-string">&quot;accuracy&quot;</span>])</code></pre>
<p>Um exemplo de como ficará nossa rede neural</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-bGrCK2cuKp04n%2Fcontent%2Fadfc432625c97242.png?alt=media&amp;token=9114188e-3b1a-4085-af50-7be97749b9d1" alt="" loading="lazy" decoding="async">
<p>Com o modelo devidamente configurado para receber os dados de treino informaos à ele:</p>
<ul>
<li><strong>x</strong>: dados de treino do modelo, por utilizarmos um objeto do tipo `tf.data.dataset` não precisamos informar a variável resposta `y` já que ela está incorporada em nosso dataset</li>
<li><strong>epochs</strong>: número de iterações entre os dados que será executado pela rede neural, neste caso ela fará 20 iterações com dados diferentes entre cada uma para encontrar a máxima acurácia.</li>
<li><strong>validation_data</strong>: dados de teste que rede neural irá utilizar para validar a acurácia do modelo à cada iteração (<em>epoch</em>).</li>
</ul>
<pre class="code"><code class="hljs">modelo.<span class="hljs-title function_">fit</span>(
  x=treino_ds,
  epochs=<span class="hljs-number">20</span>,
  validation_data=teste_ds
)</code></pre>
<p>Ao final da execução o modelo chegou em <strong>85,5%</strong> de assertividade!</p>
<p><strong>Teste do modelo</strong></p>
<p>Utilizaremos como exemplo um paciente que sabemos que possui um problema do coração</p>
<pre class="code"><code class="hljs">dados[dados[<span class="hljs-string">&#x27;target&#x27;</span>] == <span class="hljs-number">1</span>].<span class="hljs-title function_">head</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-bGrCK2cuKp04n%2Fcontent%2F97e7f1a35ea25410.png?alt=media&amp;token=91bae203-4672-4dc8-9caf-d0fabe12a30e" alt="" loading="lazy" decoding="async">
<p>A rede neural não indica se a pessoa terá ou não um problema cardíaco, mas sim a probabilidade de ela possuir este problema. Neste caso as chances são de <strong>73,6%</strong></p>
<pre class="code"><code class="hljs">teste = {
    <span class="hljs-string">&quot;age&quot;</span>: <span class="hljs-number">67</span>,
    <span class="hljs-string">&quot;sex&quot;</span>: <span class="hljs-number">1</span>,
    <span class="hljs-string">&quot;cp&quot;</span>: <span class="hljs-number">4</span>,
    <span class="hljs-string">&quot;trestbps&quot;</span>: <span class="hljs-number">160</span>,
    <span class="hljs-string">&quot;chol&quot;</span>: <span class="hljs-number">286</span>,
    <span class="hljs-string">&quot;fbs&quot;</span>: <span class="hljs-number">0</span>,
    <span class="hljs-string">&quot;restecg&quot;</span>: <span class="hljs-number">2</span>,
    <span class="hljs-string">&quot;thalach&quot;</span>: <span class="hljs-number">108</span>,
    <span class="hljs-string">&quot;exang&quot;</span>: <span class="hljs-number">1</span>,
    <span class="hljs-string">&quot;oldpeak&quot;</span>: <span class="hljs-number">1.5</span>,
    <span class="hljs-string">&quot;slope&quot;</span>: <span class="hljs-number">2</span>,
    <span class="hljs-string">&quot;ca&quot;</span>: <span class="hljs-number">3</span>,
    <span class="hljs-string">&quot;thal&quot;</span>: <span class="hljs-string">&quot;normal&quot;</span>,
}</code></pre>
<pre class="code"><code class="hljs">input_dict = {
    name: tf.<span class="hljs-title function_">convert_to_tensor</span>([value]) <span class="hljs-keyword">for</span> name, 
    value <span class="hljs-keyword">in</span> teste.<span class="hljs-title function_">items</span>()
}
    
predicao = modelo.<span class="hljs-title function_">predict</span>(input_dict)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-built_in">print</span>(
    <span class="hljs-string">&quot;Esta pessoa possui uma probabilidade de %.1f porcento de ter um problema do coração de acordo com o modelo.&quot;</span> 
    % (<span class="hljs-number">100</span> * predicao[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>],)
)</code></pre>
<pre class="code"><code class="hljs">
### 
<span class="hljs-title class_">Esta</span> pessoa possui uma probabilidade de <span class="hljs-number">73.6</span> porcento de ter um problema <span class="hljs-keyword">do</span> coração de acordo com o modelo.</code></pre>
<p>Pegando como base agora um paciente que sabemos que não possui problemas cardíacos, vemos que as chances de desenvolver algo sério de acordo com o modelo é de <strong>49,7%</strong></p>
<pre class="code"><code class="hljs">dados[dados[<span class="hljs-string">&#x27;target&#x27;</span>] == <span class="hljs-number">0</span>].<span class="hljs-title function_">head</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-bGrCK2cuKp04n%2Fcontent%2Fbd46338785899ce7.png?alt=media&amp;token=7cad9836-f939-41ff-a6a3-488ee514320e" alt="" loading="lazy" decoding="async">
<pre class="code"><code class="hljs">teste = {
    <span class="hljs-string">&quot;age&quot;</span>: <span class="hljs-number">63</span>,
    <span class="hljs-string">&quot;sex&quot;</span>: <span class="hljs-number">1</span>,
    <span class="hljs-string">&quot;cp&quot;</span>: <span class="hljs-number">1</span>,
    <span class="hljs-string">&quot;trestbps&quot;</span>: <span class="hljs-number">145</span>,
    <span class="hljs-string">&quot;chol&quot;</span>: <span class="hljs-number">233</span>,
    <span class="hljs-string">&quot;fbs&quot;</span>: <span class="hljs-number">1</span>,
    <span class="hljs-string">&quot;restecg&quot;</span>: <span class="hljs-number">2</span>,
    <span class="hljs-string">&quot;thalach&quot;</span>: <span class="hljs-number">150</span>,
    <span class="hljs-string">&quot;exang&quot;</span>: <span class="hljs-number">0</span>,
    <span class="hljs-string">&quot;oldpeak&quot;</span>: <span class="hljs-number">2.3</span>,
    <span class="hljs-string">&quot;slope&quot;</span>: <span class="hljs-number">3</span>,
    <span class="hljs-string">&quot;ca&quot;</span>: <span class="hljs-number">0</span>,
    <span class="hljs-string">&quot;thal&quot;</span>: <span class="hljs-string">&quot;fixed&quot;</span>,
}</code></pre>
<pre class="code"><code class="hljs">input_dict = {
    name: tf.<span class="hljs-title function_">convert_to_tensor</span>([value]) <span class="hljs-keyword">for</span> name, 
    value <span class="hljs-keyword">in</span> teste.<span class="hljs-title function_">items</span>()}
    
predicao = modelo.<span class="hljs-title function_">predict</span>(input_dict)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-built_in">print</span>(
    <span class="hljs-string">&quot;Esta pessoa possui uma probabilidade de %.1f porcento de ter um problema do coração de acordo com o modelo&quot;</span> 
    % (<span class="hljs-number">100</span> * predicao[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>],)
)</code></pre>
<pre class="code"><code class="hljs">####
<span class="hljs-title class_">Esta</span> pessoa possui uma probabilidade de <span class="hljs-number">49.7</span> porcento de ter um problema <span class="hljs-keyword">do</span> coração de acordo com o modelo</code></pre>
<p>Os códigos utilizados aqui podem ser acessos em<br><a href="https://github.com/marcosmhs/Heart-Disease-Cleveland" target="_blank" rel="noopener"><strong>marcosmhs/Heart-Disease-Cleveland (github.com)</strong></a></p>
]]></content:encoded>
  </item>
  <item>
    <title>Regressão Multinível</title>
    <link>https://www.marcosmhs.com.br/artigos/regressao-multinivel/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/regressao-multinivel/</guid>
    <pubDate>Tue, 21 Jun 2022 22:55:05 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>RStudio</category>
    <category>Modelos GLM</category>
    <description>O texto de hoje é sobre uma outra forma de criar um modelo capaz de “prever” um resultado baseado em dados. Meus últimos dois textos abordaram formas de criar…</description>
    <content:encoded><![CDATA[<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2F5fadd8b68c99a43c.png?alt=media&amp;token=f0c8fa4d-f22b-4947-8969-932402d20580" alt="" loading="lazy" decoding="async">
<h2 id="uma-rapida-introducao">Uma rápida introdução</h2>
<p>O texto de hoje é sobre uma outra forma de criar um modelo capaz de “prever” um resultado baseado em dados. Meus últimos dois textos abordaram formas de criar redes neurais e como usá-las para prever resultados: <a href="https://www.linkedin.com/pulse/rede-neural-recorrente-para-identifica%C3%A7%C3%A3o-de-d%C3%ADgitos-marcos-silva/" target="_blank" rel="noopener">Rede neural recorrente para identificação de dígitos</a> e <a href="https://rpubs.com/marcosmhs/rede_lstm_predicao_dolar" target="_blank" rel="noopener">Rede LSTM para predição da cotação do dólar</a>.</p>
<p>Hoje trago uma outra abordagem, tão importante quanto as redes neurais e capaz de criar resultados mais claros!</p>
<p>Imagine que você gostaria de avaliar qual seria o resultado de sua empresa usando por exemplo a nota do NPS que suas lojas (ou loja) recebeu. Para lhe ajudar com este cálculo você possui uma base de dados com registros históricos, acumulando as vendas dos últimos 12 meses e das notas que as lojas registraram.</p>
<p>Se colocarmos estes dados em um gráfico do excel com receita no eixo X e NPS no eixo Y, teremos o seguinte resultado:</p>
<figure><img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2Ff67f875031fe1f84.png?alt=media&amp;token=7cd9e15c-a9de-41d9-b3e2-ae5e9aec301e" alt="Exemplo de Reta de regressão" loading="lazy" decoding="async"><figcaption>Exemplo de Reta de regressão</figcaption></figure>
<p>Cada ponto preto representa o cruzamento de resultado e NPS de uma loja e a linha azul é a reta de regressão, uma linha que tenta passar o mais próximo possível de todos os pontos, numa tentativa de resumir o gráfico a uma só informação.</p>
<p>Um modelo de regressão tenta estimar qual seria a reta para dados que não estão em sua base, usando apenas as informações existentes. <strong>Por exemplo, qual será a receita de uma loja se ela tiver uma nota NPS 87,8?</strong></p>
<p>A fórmula base para explicar um modelo de regressão linear com base neste exemplo seria:</p>
<p>Y = γ0 + NPS1∗γ1 + ϵY</p>
<p>Onde :</p>
<ul>
<li>γ0(gama 0) representa uma a média da variável resposta</li>
<li>γ1 (gama 1) representa a participação do NPS na inclinação da reta de regressão</li>
<li>ϵ (epsilon) representa a distância entre o valor real da receita e o valor que foi previsto pelos termos γ1γ1, este valor também é chamado de erro ou resíduo</li>
</ul>
<p>O desafio neste tipo de modelo é encontrar os valores de γ0γ0 e γ1γ1para que possamos substituí-los em nossa fórmula e encontrar o valor da receita.</p>
<h2 id="e-quando-o-mundo-nao-e-linear-e-quase-sempre-nao-e">E quando o mundo não é linear? E quase sempre não é!</h2>
<p>A modelagem linear cumpre bem o seu papel em determinados cenários, mas em muitos casos ela sozinha não é suficiente para explicar um mundo tão diverso. <strong>E é aí que entra a modelagem multinível</strong>! Um modelo que prevê que o mundo é feito de grupos e que estes grupos exercem influência sobre os dados. Este modelo considera que os dados podem ser agrupados em até três níveis:</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2Fcfc13843bbb8bf3d.png?alt=media&amp;token=df5620dd-375c-4e8e-b2bd-1b81ceb7301d" alt="" loading="lazy" decoding="async">
<p>Onde:</p>
<ul>
<li>Grupo 1 (<em>t</em>), podemos trabalhar com uma escala de tempo, por exemplo, se houver dados de minha loja segmentados por mês;</li>
<li>Grupo 2 (<em>i</em>), temos o indivíduo, no nosso exemplo a loja;</li>
<li>Grupo 3 (<em>j</em>) temos o agrupamento, neste caso a cidade.</li>
</ul>
<p>Neste cenário podemos avaliar que as lojas podem ter comportamento diferente dependendo da cidade onde estão localizadas e que variáveis específicas destas cidades podem influenciar em seu resultado, além do NPS.</p>
<p>Neste caso trabalharemos com os grupos <em>i</em> e <em>j</em> apenas, respectivamente os níveis 1 (loja) e 2 (cidade).</p>
<h2 id="preparacao-dos-pacotes">Preparação dos pacotes</h2>
<pre class="code"><code class="hljs">pacotes = <span class="hljs-title function_">c</span>(<span class="hljs-string">&quot;plotly&quot;</span>,<span class="hljs-string">&quot;tidyverse&quot;</span>,<span class="hljs-string">&quot;reshape2&quot;</span>,<span class="hljs-string">&quot;knitr&quot;</span>,<span class="hljs-string">&quot;kableExtra&quot;</span>,<span class="hljs-string">&quot;rgl&quot;</span>,<span class="hljs-string">&quot;car&quot;</span>, <span class="hljs-string">&quot;nlme&quot;</span>,<span class="hljs-string">&quot;lmtest&quot;</span>,<span class="hljs-string">&quot;fastDummies&quot;</span>,<span class="hljs-string">&quot;msm&quot;</span>,<span class="hljs-string">&quot;lmeInfo&quot;</span>,<span class="hljs-string">&quot;jtools&quot;</span>, <span class="hljs-string">&quot;data.table&quot;</span>, <span class="hljs-string">&quot;olsrr&quot;</span>)

<span class="hljs-keyword">if</span>(<span class="hljs-title function_">sum</span>(<span class="hljs-keyword">as</span>.<span class="hljs-title function_">numeric</span>(!pacotes %<span class="hljs-keyword">in</span>% installed.<span class="hljs-title function_">packages</span>())) != <span class="hljs-number">0</span>){
  instalador &lt;- pacotes[!pacotes %<span class="hljs-keyword">in</span>% installed.<span class="hljs-title function_">packages</span>()]
  <span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:<span class="hljs-title function_">length</span>(instalador)) {
    install.<span class="hljs-title function_">packages</span>(instalador, dependencies = T)
    <span class="hljs-title function_">break</span>()}
  <span class="hljs-title function_">sapply</span>(pacotes, require, character = T) 
} <span class="hljs-keyword">else</span> {
  <span class="hljs-title function_">sapply</span>(pacotes, require, character = T) 
}</code></pre>
<p>A função stderr_nlme, de autoria dos professores Fávero e Rafael Sousa ajuda a identificar a significância estatística dos dados de cada nível e de certa forma a calcular o quanto do comportamento dos dados é explicado por cada nível.</p>
<pre class="code"><code class="hljs">stderr_nlme &lt;- <span class="hljs-title function_">function</span>(model){
  <span class="hljs-keyword">if</span>(<span class="hljs-keyword">base</span>::<span class="hljs-class"><span class="hljs-keyword">class</span>(<span class="hljs-title">model</span>) != &quot;<span class="hljs-title">lme</span>&quot;)</span>{
    <span class="hljs-keyword">base</span>::<span class="hljs-title function_">message</span>(<span class="hljs-string">&quot;Use a lme object model from nlme package&quot;</span>)
    <span class="hljs-title function_">stop</span>()}
  resume &lt;- <span class="hljs-keyword">base</span>::<span class="hljs-title function_">summary</span>(model)
  <span class="hljs-keyword">if</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">length</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">names</span>(model$groups))==<span class="hljs-number">1</span>){
    m.type &lt;- <span class="hljs-string">&quot;HLM2&quot;</span>
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">length</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">names</span>(model$groups))==<span class="hljs-number">2</span>){
    m.type &lt;- <span class="hljs-string">&quot;HLM3&quot;</span>
  }
  <span class="hljs-keyword">if</span>(m.type == <span class="hljs-string">&quot;HLM2&quot;</span>){
    vcov_matrix &lt;- model$apVar
    logs_sd_re &lt;- <span class="hljs-keyword">base</span>::<span class="hljs-title function_">attr</span>(vcov_matrix,<span class="hljs-string">&quot;Pars&quot;</span>)
    <span class="hljs-keyword">if</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">length</span>(logs_sd_re)==<span class="hljs-number">2</span>){
      stderr_tau00 &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x1)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      stderr_sigma &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x2)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      results &lt;- <span class="hljs-keyword">base</span>::data.<span class="hljs-title function_">frame</span>(`RE <span class="hljs-title class_">Components</span>`=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-string">&quot;Var(v0j)&quot;</span>,<span class="hljs-string">&quot;Var(e)&quot;</span>),
                                  `<span class="hljs-title class_">Variance</span> <span class="hljs-title class_">Estimatives</span>`= <span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>,
                                                                  <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re[[<span class="hljs-number">2</span>]])^<span class="hljs-number">2</span>),
                                  `<span class="hljs-title class_">Std</span> <span class="hljs-title class_">Err</span>.`=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(stderr_tau00,
                                                     stderr_sigma),
                                  z=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>/stderr_tau00,
                                            <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re[[<span class="hljs-number">2</span>]])^<span class="hljs-number">2</span>/stderr_sigma),
                                  `p-value`=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">round</span>(stats::<span class="hljs-title function_">pnorm</span>(q=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>/stderr_tau00,
                                                                               <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re[[<span class="hljs-number">2</span>]])^<span class="hljs-number">2</span>/stderr_sigma),
                                                                     lower.tail=F)*<span class="hljs-number">2</span>,<span class="hljs-number">3</span>))
      <span class="hljs-title function_">return</span>(results)
    }
    <span class="hljs-keyword">else</span>{
      stderr_tau00 &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x1)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      stderr_tau01 &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x2)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      stderr_sigma &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x4)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      results &lt;- <span class="hljs-keyword">base</span>::data.<span class="hljs-title function_">frame</span>(<span class="hljs-title class_">Components</span>=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-string">&quot;Var(v0j)&quot;</span>,<span class="hljs-string">&quot;Var(v1j)&quot;</span>,<span class="hljs-string">&quot;Var(e)&quot;</span>),
                                  `<span class="hljs-title class_">Variance</span> <span class="hljs-title class_">Estimatives</span>`= <span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>,
                                                       <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re[[<span class="hljs-number">2</span>]])^<span class="hljs-number">2</span>,
                                                       <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re[[<span class="hljs-number">4</span>]])^<span class="hljs-number">2</span>),
                                  `<span class="hljs-title class_">Std</span> <span class="hljs-title class_">Err</span>.`=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(stderr_tau00,
                                                  stderr_tau01,
                                                  stderr_sigma),
                                  z=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>/stderr_tau00,
                                            <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re[[<span class="hljs-number">2</span>]])^<span class="hljs-number">2</span>/stderr_tau01,
                                            <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re[[<span class="hljs-number">4</span>]])^<span class="hljs-number">2</span>/stderr_sigma),
                                  `p-value`=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">round</span>(stats::<span class="hljs-title function_">pnorm</span>(q=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>/stderr_tau00,
                                                                               <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re[[<span class="hljs-number">2</span>]])^<span class="hljs-number">2</span>/stderr_tau01,
                                                                               <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re[[<span class="hljs-number">4</span>]])^<span class="hljs-number">2</span>/stderr_sigma),
                                                                     lower.tail=F)*<span class="hljs-number">2</span>,<span class="hljs-number">3</span>))
      <span class="hljs-title function_">return</span>(results)
    }
  }
  <span class="hljs-keyword">if</span>(m.type == <span class="hljs-string">&quot;HLM3&quot;</span>){
    vcov_matrix &lt;- model$apVar
    logs_sd_re &lt;-  <span class="hljs-keyword">base</span>::<span class="hljs-title function_">attr</span>(vcov_matrix,<span class="hljs-string">&quot;Pars&quot;</span>)
    <span class="hljs-keyword">if</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">length</span>(logs_sd_re) == <span class="hljs-number">3</span>){
      stderr_tau_r000 &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x1)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      stderr_tau_u000 &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x2)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      stderr_sigma &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x3)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      results &lt;- <span class="hljs-keyword">base</span>::data.<span class="hljs-title function_">frame</span>(<span class="hljs-title class_">Components</span>=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-string">&quot;Var(t00k)&quot;</span>,<span class="hljs-string">&quot;Var(v0jk)&quot;</span>,<span class="hljs-string">&quot;Var(e)&quot;</span>),
                                  <span class="hljs-title class_">Estimatives</span>=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">2</span>]]^<span class="hljs-number">2</span>,
                                                      <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>,
                                                      <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">3</span>]]^<span class="hljs-number">2</span>),
                                  Std_Err=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(stderr_tau_u000,
                                                  stderr_tau_r000,
                                                  stderr_sigma),
                                  z=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">2</span>]]^<span class="hljs-number">2</span>/stderr_tau_u000,
                                            <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>/stderr_tau_r000,
                                            <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">3</span>]]^<span class="hljs-number">2</span>/stderr_sigma),
                                  `p-value`=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">round</span>(stats::<span class="hljs-title function_">pnorm</span>(q=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">2</span>]]^<span class="hljs-number">2</span>/stderr_tau_u000,
                                                                               <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>/stderr_tau_r000,
                                                                               <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">3</span>]]^<span class="hljs-number">2</span>/stderr_sigma),
                                                                     lower.tail=F)*<span class="hljs-number">2</span>,<span class="hljs-number">3</span>))
      <span class="hljs-title function_">return</span>(results)
    } 
    <span class="hljs-keyword">else</span>{
      stderr_tau_r000 &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x1)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      stderr_tau_r100 &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x2)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      stderr_tau_u000 &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x4)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      stderr_tau_u100 &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x5)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      stderr_sigma &lt;- msm::<span class="hljs-title function_">deltamethod</span>(~<span class="hljs-title function_">exp</span>(x7)^<span class="hljs-number">2</span>,logs_sd_re,vcov_matrix)
      results &lt;- <span class="hljs-keyword">base</span>::data.<span class="hljs-title function_">frame</span>(`RE_Components`=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-string">&quot;Var(t00k)&quot;</span>,<span class="hljs-string">&quot;Var(t10k)&quot;</span>,
                                                          <span class="hljs-string">&quot;Var(v0jk)&quot;</span>,<span class="hljs-string">&quot;Var(v1jk)&quot;</span>,
                                                          <span class="hljs-string">&quot;Var(e)&quot;</span>),
                                  `<span class="hljs-title class_">Variance</span> <span class="hljs-title class_">Estimatives</span>`=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">4</span>]]^<span class="hljs-number">2</span>,
                                                                 <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">5</span>]]^<span class="hljs-number">2</span>,
                                                                 <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>,
                                                                 <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">2</span>]]^<span class="hljs-number">2</span>,
                                                                 <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">7</span>]]^<span class="hljs-number">2</span>),
                                  `<span class="hljs-title class_">Std</span> <span class="hljs-title class_">Err</span>.`=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(stderr_tau_u000,
                                                     stderr_tau_u100,
                                                     stderr_tau_r000,
                                                     stderr_tau_r100,
                                                     stderr_sigma),
                                  z=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">4</span>]]^<span class="hljs-number">2</span>/stderr_tau_u000,
                                            <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">5</span>]]^<span class="hljs-number">2</span>/stderr_tau_u100,
                                            <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>/stderr_tau_r000,
                                            <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">2</span>]]^<span class="hljs-number">2</span>/stderr_tau_r100,
                                            <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">7</span>]]^<span class="hljs-number">2</span>/stderr_sigma),
                                  `p-value`=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">round</span>(stats::<span class="hljs-title function_">pnorm</span>(q=<span class="hljs-keyword">base</span>::<span class="hljs-title function_">c</span>(<span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">4</span>]]^<span class="hljs-number">2</span>/stderr_tau_u000,
                                                                               <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">5</span>]]^<span class="hljs-number">2</span>/stderr_tau_u100,
                                                                               <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">1</span>]]^<span class="hljs-number">2</span>/stderr_tau_r000,
                                                                               <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">2</span>]]^<span class="hljs-number">2</span>/stderr_tau_r100,
                                                                               <span class="hljs-keyword">base</span>::<span class="hljs-title function_">exp</span>(logs_sd_re)[[<span class="hljs-number">7</span>]]^<span class="hljs-number">2</span>/stderr_sigma),
                                                                     lower.tail=F)*<span class="hljs-number">2</span>,<span class="hljs-number">3</span>))
      <span class="hljs-title function_">return</span>(results)
    }
  }
}</code></pre>
<h2 id="importacao-dos-dados-e-analise-exploratoria">Importação dos dados e análise exploratória</h2>
<pre class="code"><code class="hljs">vendas = 
  <span class="hljs-title function_">fread</span>(<span class="hljs-string">&quot;dados_vendas_totais_2021.csv&quot;</span>, dec =<span class="hljs-string">&quot;,&quot;</span>, sep=<span class="hljs-string">&quot;;&quot;</span>) %&gt;%
  <span class="hljs-title function_">select</span>(cidade, loja, receita, nps, inflacao) %&gt;%
  <span class="hljs-title function_">mutate</span>(loja = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(loja), cidade = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(cidade))</code></pre>
<p>Para testar o modelo vamos utilizar uma segunda base de dados semelhante à nossa base de treino (vendas) com 195 registros</p>
<pre class="code"><code class="hljs">teste = 
  <span class="hljs-title function_">fread</span>(<span class="hljs-string">&quot;dados_para_teste.csv&quot;</span>, dec =<span class="hljs-string">&quot;,&quot;</span>, sep=<span class="hljs-string">&quot;;&quot;</span>) %&gt;%
  <span class="hljs-title function_">select</span>(cidade, loja, receita, nps, inflacao) %&gt;%
  <span class="hljs-title function_">mutate</span>(loja = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(loja), cidade = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(cidade))</code></pre>
<p>A visualização das primeiras 5 linhas das cidades 1 e 2, foi aplicado a função scalepara evitar que os dados sejam expostos</p>
<pre class="code"><code class="hljs"><span class="hljs-title function_">rbind</span>(
  vendas %&gt;% 
    <span class="hljs-title function_">filter</span>(cidade == <span class="hljs-number">1</span>) %&gt;% 
    <span class="hljs-title function_">filter</span>(<span class="hljs-title function_">row_number</span>() &lt;= <span class="hljs-number">5</span>),
  vendas %&gt;% 
    <span class="hljs-title function_">filter</span>(cidade == <span class="hljs-number">2</span>) %&gt;% 
    <span class="hljs-title function_">filter</span>(<span class="hljs-title function_">row_number</span>() &lt;= <span class="hljs-number">5</span>)) %&gt;%
  <span class="hljs-title function_">kable</span>() %&gt;%
  <span class="hljs-title function_">kable_styling</span>(bootstrap_options = <span class="hljs-string">&quot;striped&quot;</span>, 
                position = <span class="hljs-string">&quot;center&quot;</span>, 
                full_width = F, 
                font_size = <span class="hljs-number">14</span>)</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2F313128bd2f6eca4d.png?alt=media&amp;token=2360b95c-25c9-4acb-aec6-97a72aa58ade" alt="" loading="lazy" decoding="async">
<pre class="code"><code class="hljs">vendas %&gt;% 
  <span class="hljs-title function_">group_by</span>(cidade) %&gt;% 
  <span class="hljs-title function_">mutate</span>(linhas = <span class="hljs-number">1</span>:<span class="hljs-title function_">n</span>()) %&gt;% 
  <span class="hljs-title function_">mutate</span>(x = <span class="hljs-title function_">unlist</span>(<span class="hljs-title function_">density</span>(receita, n = <span class="hljs-title function_">max</span>(linhas))[<span class="hljs-string">&quot;x&quot;</span>]),
         y = <span class="hljs-title function_">unlist</span>(<span class="hljs-title function_">density</span>(receita, n = <span class="hljs-title function_">max</span>(linhas))[<span class="hljs-string">&quot;y&quot;</span>])) %&gt;%
  <span class="hljs-title function_">ggplot</span>() +
  <span class="hljs-title function_">geom_area</span>(<span class="hljs-title function_">aes</span>(x = x, y = y, group = cidade, fill = cidade), color = <span class="hljs-string">&quot;black&quot;</span>, alpha = <span class="hljs-number">0.4</span>) +
  <span class="hljs-title function_">geom_histogram</span>(<span class="hljs-title function_">aes</span>(x = receita, 
                     y = ..density.., 
                     fill = cidade), 
                 color = <span class="hljs-string">&quot;black&quot;</span>, 
                 position = <span class="hljs-string">&#x27;identity&#x27;</span>, 
                 alpha = <span class="hljs-number">0.3</span>) +
  <span class="hljs-title function_">facet_wrap</span>(~ cidade) +
  <span class="hljs-title function_">scale_fill_viridis_d</span>() +
  <span class="hljs-title function_">scale_color_viridis_d</span>() +
  <span class="hljs-title function_">theme_classic</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2F6e50a97bd25e687a.png?alt=media&amp;token=0f7a6fe2-a425-4e29-ad41-04d9ce249474" alt="" loading="lazy" decoding="async">
<pre class="code"><code class="hljs">vendas %&gt;%
  <span class="hljs-title function_">ggplot</span>() +
  <span class="hljs-title function_">geom_bar</span>(<span class="hljs-title function_">aes</span>(x = cidade, y=inflacao, fill = cidade), stat = <span class="hljs-string">&quot;identity&quot;</span>) +
  <span class="hljs-title function_">scale_y_continuous</span>() +
  <span class="hljs-title function_">scale_fill_viridis_d</span>() +
  <span class="hljs-title function_">theme_minimal</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2F1c647b8d9ad4513b.png?alt=media&amp;token=aa7a027c-6ffb-4243-9d10-4fe275a7d299" alt="" loading="lazy" decoding="async">
<p>Temos aqui os indícios necessário para iniciar a exploração de modelos de regressão!</p>
<h2 id="criacao-dos-modelos">Criação dos modelos</h2>
<p>Para a modelagem multinível utiliza-se a técnica <strong>step-up</strong> onde o modelo é otimizado a cada execução até obter-se sua versão final. Para verificar o modelo vamos utilizar o <strong>BIC (bayesian information criterion)</strong> critério que avalia o quão perto o modelo está dados reais considerando também as variáveis explicativas.</p>
<p>O primeiro modelo a ser criado é o <strong>modelo nulo</strong>, que não considera nenhuma variável preditora, apenas a receita e o agrupamento por cidade. Sua fórmula pode é:</p>
<p>receita_ij = γ00+ν0j+ϵi</p>
<p>Onde:</p>
<ul>
<li>γ00 representa a média geral da variável receita</li>
<li>ν0j representa a influência da cidade sobre a receita</li>
<li>νij representa a distância entre a receita calculada para aquela observação e o valor real</li>
</ul>
<p>Observe que todos os dados são subscritos de com i e j onde i representa o dado no nível loja e j no nível cidade.</p>
<p>No R a execução desta fórmula é feita pelo comando lme do pacote nlme</p>
<pre class="code"><code class="hljs"><span class="hljs-meta">#fixed é a fórmula base, de regressão linear</span>
<span class="hljs-meta">#random é a fórmula de agrupamento dos dados, neste caso cidade</span>
hlm_nulo = 
  lme(<span class="hljs-keyword">fixed</span> = receita ~<span class="hljs-number">1</span>, 
      random = ~<span class="hljs-number">1</span> | cidade, 
      data = vendas,
      method = <span class="hljs-string">&quot;REML&quot;</span>)

BIC(hlm_nulo)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">## [1] 14212.24</span></code></pre>
<p>O BIC de nosso modelo base é 14212.24, ele será utilizado mais adiante para compararmos o ganho dos próximos modelos. Quando menor ele for, melhor!</p>
<pre class="code"><code class="hljs"><span class="hljs-title function_">stderr_nlme</span>(hlm_nulo)</code></pre>
<pre class="code"><code class="hljs">##   RE.<span class="hljs-title class_">Components</span> <span class="hljs-title class_">Variance</span>.<span class="hljs-title class_">Estimatives</span>  <span class="hljs-title class_">Std</span>.<span class="hljs-title class_">Err</span>.        z p.value
## <span class="hljs-number">1</span>      <span class="hljs-title class_">Var</span>(v0j)             <span class="hljs-number">626248.2</span> <span class="hljs-number">223061.02</span>  <span class="hljs-number">2.80752</span>   <span class="hljs-number">0.005</span>
## <span class="hljs-number">2</span>        <span class="hljs-title class_">Var</span>(e)             <span class="hljs-number">254473.4</span>  <span class="hljs-number">11949.33</span> <span class="hljs-number">21.29604</span>   <span class="hljs-number">0.000</span></code></pre>
<p>Outra informação importante vem através do método stderr_nlme, nele podemos ver que o p-value de nossa variável receita (v0j) é estatisticamente significativa (menor que 0,05), indicando que o modelo multinível é aplicável à este caso. Se ela fosse superior a 0,05 o modelo de regressão linear simples seria o mais indicado.</p>
<p>Utilizaremos agora a base de testes para executar nosso modelo e comparar se os resultados previstos estão próximos do resultado real.</p>
<pre class="code"><code class="hljs">teste$hlm_nulo_fitted = <span class="hljs-title function_">predict</span>(hlm_nulo, teste)</code></pre>
<pre class="code"><code class="hljs">teste %&gt;%  
  <span class="hljs-title function_">ggplot</span>() +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y = hlm_nulo_fitted),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y = receita), method = <span class="hljs-string">&quot;lm&quot;</span>, 
              color = <span class="hljs-string">&quot;gray44&quot;</span>, size = <span class="hljs-number">1.05</span>,
              linetype = <span class="hljs-string">&quot;longdash&quot;</span>) +
  <span class="hljs-title function_">labs</span>(x = <span class="hljs-string">&quot;Receita real&quot;</span>, y = <span class="hljs-string">&quot;Valores Preditos&quot;</span>) +
  <span class="hljs-title function_">theme_bw</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2F032977d4b9c23876.png?alt=media&amp;token=a325fe7c-b2f1-45cf-81f6-6c2666e860cc" alt="" loading="lazy" decoding="async">
<p>Observe que a linha azul (modelo nulo) chega a tocar a linha pontilhada (resultado perfeito), mas apresenta considerável diferença no início e no final da reta.</p>
<h2 id="modelo-com-interceptos-aleatorios">Modelo com interceptos aleatórios</h2>
<p>O próximo passo, é a <strong>modelo com interceptos aleatórios</strong> que considera apenas efeito que a cidade (intercepto) exerce sobre a receita:</p>
<p>receita_ij=γ00+γ10∗npsij+ν0j+ϵ_ij</p>
<p>Onde:</p>
<ul>
<li>γ00 representa a média geral da variável receita</li>
<li>γ10 representa a inclinação da reta de receita de acordo com o avanço do NPS</li>
<li>ν0j representa a influência da cidade sobre a receita</li>
<li>ν_ij representa a distância entre a receita calculada para aquela observação e o valor real</li>
</ul>
<p>No R a fórmula pode ser representada como no exemplo abaixo:</p>
<pre class="code"><code class="hljs">hlm_intercept_aleatorios = 
  <span class="hljs-title function_">lme</span>(fixed = receita ~ nps  + inflacao,
      random = ~<span class="hljs-number">1</span> | cidade,
      data = vendas,
      method = <span class="hljs-string">&quot;REML&quot;</span>)</code></pre>
<pre class="code"><code class="hljs">#observação <span class="hljs-keyword">do</span> BIC <span class="hljs-keyword">do</span> modelo
BIC(hlm_intercept_aleatorios)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">## [1] 13421.34</span></code></pre>
<p>O indicador BIC, que no modelo nulo, é de 14212,24 foi reduzido para 13421,35 indicando que a variável NPS possui grande efeito sobre a receita.</p>
<pre class="code"><code class="hljs"><span class="hljs-title function_">stderr_nlme</span>(hlm_intercept_aleatorios)</code></pre>
<pre class="code"><code class="hljs">##   RE.<span class="hljs-title class_">Components</span> <span class="hljs-title class_">Variance</span>.<span class="hljs-title class_">Estimatives</span>  <span class="hljs-title class_">Std</span>.<span class="hljs-title class_">Err</span>.         z p.value
## <span class="hljs-number">1</span>      <span class="hljs-title class_">Var</span>(v0j)             <span class="hljs-number">142365.8</span> <span class="hljs-number">52902.868</span>  <span class="hljs-number">2.691079</span>   <span class="hljs-number">0.007</span>
## <span class="hljs-number">2</span>        <span class="hljs-title class_">Var</span>(e)             <span class="hljs-number">110375.8</span>  <span class="hljs-number">5185.945</span> <span class="hljs-number">21.283637</span>   <span class="hljs-number">0.000</span></code></pre>
<p>O <em>p-value</em> do nível v0j segue abaixo de 0,05 indicando que o modelo é estatisticamente significativo.</p>
<p>Vamos verificar agora como os modelos se aproximam do valor ideal:</p>
<pre class="code"><code class="hljs">teste$hlm_intercept_aleatorios_fitted = <span class="hljs-title function_">predict</span>(hlm_intercept_aleatorios, teste)

teste %&gt;%
  
  <span class="hljs-title function_">ggplot</span>() +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y = hlm_nulo_fitted, color = <span class="hljs-string">&quot;Modelo Nulo&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y= hlm_intercept_aleatorios_fitted, color = <span class="hljs-string">&quot;Interceptos Aletaórios&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +

  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y = receita), method = <span class="hljs-string">&quot;lm&quot;</span>, 
              color = <span class="hljs-string">&quot;gray44&quot;</span>, size = <span class="hljs-number">1.05</span>,
              linetype = <span class="hljs-string">&quot;longdash&quot;</span>) +
  <span class="hljs-title function_">scale_color_manual</span>(<span class="hljs-string">&quot;Modelos:&quot;</span>, 
                     values = <span class="hljs-title function_">c</span>(<span class="hljs-string">&quot;deepskyblue1&quot;</span>, <span class="hljs-string">&quot;maroon1&quot;</span>)) +
  <span class="hljs-title function_">labs</span>(x = <span class="hljs-string">&quot;Receita Real&quot;</span>, y = <span class="hljs-string">&quot;Receita Prevista&quot;</span>) +
  <span class="hljs-title function_">theme_bw</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2F2159e1684150151a.png?alt=media&amp;token=d423e54c-3e5c-4181-9060-20fe1e578808" alt="" loading="lazy" decoding="async">
<p>Observe que a linha do modelo com interceptos aleatórios chegou muito perto da reta ideal</p>
<h2 id="modelo-com-interceptos-e-inclinacoes-aleatorias">Modelo com interceptos e inclinações aleatórias</h2>
<p>O próximo passo é verificarmos o efeito que a cidade exerce sobre o NPS e a receita e pode ser descrita pela função:</p>
<p>receita_ij=γ00 + γ10∗nps_ij + ν0j + ν1j∗nps_ij + ϵ_ij</p>
<p>Onde:</p>
<ul>
<li>γ00 representa a média geral da variável receita</li>
<li>γ10 representa a inclinação da reta de receita de acordo com o avanço do NPS</li>
<li>ν0j representa a influência da cidade sobre a receita</li>
<li>νij representa a distância entre a receita calculada para aquela observação e o valor real</li>
</ul>
<p>Observe que agora temos ν_ij influenciando o valor de NPS: ν_ij∗nps_ij</p>
<p>No R teremos:</p>
<pre class="code"><code class="hljs">hlm_intercept_inclin = 
  <span class="hljs-title function_">lme</span>(fixed = receita ~ nps  + inflacao, 
      random = ~ nps  | cidade, 
      data = vendas,
      method = <span class="hljs-string">&quot;REML&quot;</span>)

BIC(hlm_intercept_inclin)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">## [1] 13299.13</span></code></pre>
<p>Nesta terceira execução observa-se uma nova queda no indicador BIC, mostrando que o volume de erros diminuiu em comparação com os modelos anteriores</p>
<pre class="code"><code class="hljs"><span class="hljs-title function_">stderr_nlme</span>(hlm_intercept_inclin)</code></pre>
<pre class="code"><code class="hljs">##   <span class="hljs-title class_">Components</span> <span class="hljs-title class_">Variance</span>.<span class="hljs-title class_">Estimatives</span>    <span class="hljs-title class_">Std</span>.<span class="hljs-title class_">Err</span>.        z p.value
## <span class="hljs-number">1</span>   <span class="hljs-title class_">Var</span>(v0j)          <span class="hljs-number">658818.6994</span> <span class="hljs-number">302905.1560</span>  <span class="hljs-number">2.17500</span>   <span class="hljs-number">0.030</span>
## <span class="hljs-number">2</span>   <span class="hljs-title class_">Var</span>(v1j)             <span class="hljs-number">123.7548</span>     <span class="hljs-number">47.6011</span>  <span class="hljs-number">2.59983</span>   <span class="hljs-number">0.009</span>
## <span class="hljs-number">3</span>     <span class="hljs-title class_">Var</span>(e)           <span class="hljs-number">90701.3200</span>   <span class="hljs-number">4301.1633</span> <span class="hljs-number">21.08763</span>   <span class="hljs-number">0.000</span></code></pre>
<p>O <em>p-value</em> do nível v0j (nível loja) e v1j seguem abaixo de 0,05 indicando que o modelo continua estatisticamente significativo.</p>
<p>Por fim vamos comparar a performance dos modelos</p>
<pre class="code"><code class="hljs">teste$hlm_intercept_inclin_fitted = 
   <span class="hljs-title function_">predict</span>(hlm_intercept_inclin, teste)

teste %&gt;%  
  <span class="hljs-title function_">ggplot</span>() +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y = hlm_nulo_fitted, color = <span class="hljs-string">&quot;Modelo Nulo&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y= hlm_intercept_aleatorios_fitted, color = <span class="hljs-string">&quot;Interceptos Aletaórios&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +
  
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y= hlm_intercept_inclin_fitted, color = <span class="hljs-string">&quot;Interceptos e Inclinações aleatórias&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +  

  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y = receita), method = <span class="hljs-string">&quot;lm&quot;</span>, 
              color = <span class="hljs-string">&quot;gray44&quot;</span>, size = <span class="hljs-number">1.05</span>,
              linetype = <span class="hljs-string">&quot;longdash&quot;</span>) +
  <span class="hljs-title function_">scale_color_manual</span>(<span class="hljs-string">&quot;Modelos:&quot;</span>, 
                     values = <span class="hljs-title function_">c</span>(<span class="hljs-string">&quot;deepskyblue1&quot;</span>, <span class="hljs-string">&quot;maroon1&quot;</span>, <span class="hljs-string">&quot;darkorchid2&quot;</span>)) +
  <span class="hljs-title function_">labs</span>(x = <span class="hljs-string">&quot;Receita Real&quot;</span>, y = <span class="hljs-string">&quot;Receita Prevista&quot;</span>) +
  <span class="hljs-title function_">theme_bw</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2Fbb826fa849d5c817.png?alt=media&amp;token=647022c4-1d64-4494-a972-2f0179e3746c" alt="" loading="lazy" decoding="async">
<h2 id="modelo-final">Modelo Final</h2>
<p>Agora que verificamos que o NPS tem efeito sobre a receita e que o agrupamento por cidade também exerce efeito sobre as demais informações, vamos verificar se as variáveis do nível de cidade, neste caso a inflação local também impacta no resultado. Teremos finalmente a fórmula completa:</p>
<p>receita_ij=γ00 + γ10∗nps_ij + γ01∗inflacao_j + γ11∗nps_ij∗inflacao_j + ν0j + ν1_j∗np_sij+ϵ_ij</p>
<p>No R teremos:</p>
<pre class="code"><code class="hljs">hlm_final = 
  <span class="hljs-title function_">lme</span>(fixed = receita ~ nps  + inflacao + nps:inflacao,
      random = ~ nps | cidade,
      data = vendas,
      method = <span class="hljs-string">&quot;REML&quot;</span>)</code></pre>
<pre class="code"><code class="hljs">BIC(hlm_final)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">## [1] 13281.57</span></code></pre>
<p>Observamos uma nova redução no BIC, indicando que o houve melhora no modelo ao incluir o efeito da inflação na receita e no NPS.</p>
<pre class="code"><code class="hljs"><span class="hljs-title function_">stderr_nlme</span>(hlm_final)</code></pre>
<pre class="code"><code class="hljs">##   <span class="hljs-title class_">Components</span> <span class="hljs-title class_">Variance</span>.<span class="hljs-title class_">Estimatives</span>     <span class="hljs-title class_">Std</span>.<span class="hljs-title class_">Err</span>.         z p.value
## <span class="hljs-number">1</span>   <span class="hljs-title class_">Var</span>(v0j)         <span class="hljs-number">392327.54923</span> <span class="hljs-number">163961.75910</span>  <span class="hljs-number">2.392799</span>   <span class="hljs-number">0.017</span>
## <span class="hljs-number">2</span>   <span class="hljs-title class_">Var</span>(v1j)             <span class="hljs-number">56.82155</span>     <span class="hljs-number">24.49188</span>  <span class="hljs-number">2.320016</span>   <span class="hljs-number">0.020</span>
## <span class="hljs-number">3</span>     <span class="hljs-title class_">Var</span>(e)          <span class="hljs-number">90634.81776</span>   <span class="hljs-number">4294.83656</span> <span class="hljs-number">21.103205</span>   <span class="hljs-number">0.000</span></code></pre>
<p>O <em>p-value</em> do nível v0j (nível loja) e v1j seguem abaixo de 0,05 ou seja, modelo significativo estatisticamente. Vamos verificar visualmente como essa nota reta se porta com a base de testes</p>
<pre class="code"><code class="hljs">teste$hlm_final_fitted = <span class="hljs-title function_">predict</span>(hlm_final, teste)</code></pre>
<pre class="code"><code class="hljs">teste %&gt;%  
  <span class="hljs-title function_">ggplot</span>() +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y = hlm_nulo_fitted, color = <span class="hljs-string">&quot;1 - Modelo Nulo&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y= hlm_intercept_aleatorios_fitted, color = <span class="hljs-string">&quot;2 - Interceptos Aletaórios&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +
  
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y= hlm_intercept_inclin_fitted, color = <span class="hljs-string">&quot;3 - Interceptos e Inclinações aleatórias&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +  
  
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y= hlm_final_fitted, color = <span class="hljs-string">&quot;4 - Modelo Final&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +  </code></pre>
<pre class="code"><code class="hljs">  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y = receita), method = <span class="hljs-string">&quot;lm&quot;</span>, 
              color = <span class="hljs-string">&quot;gray44&quot;</span>, size = <span class="hljs-number">1.05</span>,
              linetype = <span class="hljs-string">&quot;longdash&quot;</span>) +
  <span class="hljs-title function_">scale_color_manual</span>(<span class="hljs-string">&quot;Modelos:&quot;</span>, 
                     values = <span class="hljs-title function_">c</span>(<span class="hljs-string">&quot;deepskyblue1&quot;</span>, <span class="hljs-string">&quot;maroon1&quot;</span>, <span class="hljs-string">&quot;darkorchid2&quot;</span>, <span class="hljs-string">&quot;SpringGreen3&quot;</span>)) +
  <span class="hljs-title function_">labs</span>(x = <span class="hljs-string">&quot;Receita Real&quot;</span>, y = <span class="hljs-string">&quot;Receita Prevista&quot;</span>) +
  <span class="hljs-title function_">theme_bw</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2Fc28689b286a2b44e.png?alt=media&amp;token=f0dd5340-b2c5-4f05-b162-43b70c07876a" alt="" loading="lazy" decoding="async">
<h2 id="bonus">Bônus</h2>
<p>Vamos comparar o modelo HLM com um modelo re regressão linar, utilizando todas as técnicas necessárias para aumentar sua acuracidade:</p>
<p>Sabendo que temos uma variável qualitativa (a cidade) utilizaremos o método dummy_cols para transformar as colunas de forma que possam ser utilizadas em uma regressão linar. A “dumização” transformará a coluna cidade em uma série de colunas (uma para cada cidade) preenchendo seu valor com 0 ou 1 dependendo do valor da coluna original</p>
<pre class="code"><code class="hljs">vendas_dummies <span class="hljs-operator">=</span>
    dummy_cols(.data <span class="hljs-operator">=</span> vendas,
               select_columns <span class="hljs-operator">=</span> &quot;cidade&quot;,
               remove_first_dummy <span class="hljs-operator">=</span> <span class="hljs-literal">TRUE</span>,
               remove_selected_columns <span class="hljs-operator">=</span> <span class="hljs-literal">TRUE</span>)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">#16 colunas cidade foram criadas, o método dummy_cols não inclui a primeira coluna &quot;dumizada&quot; já que ela é a auzência de dados em todas as demais 16</span></code></pre>
<p>Executamos o método lmpara que seja criado o modelo de regressão simples, observe que agora cada coluna cidade deve ser informado na fórmula que seria:</p>
<p>Y= γ0 + NPS1∗γ1 + inflacao∗γ2 + cidade1∗γ3 + cidade2∗γ4 +…+ cidaden∗γn + ϵ</p>
<p>No R teremos a fórmula:</p>
<pre class="code"><code class="hljs">ols_final_dummies =
  <span class="hljs-title function_">lm</span>(formula = receita ~ nps + inflacao + cidade_2 + cidade_3 + cidade_4 + cidade_5 + cidade_6 + cidade_7 + cidade_8 + cidade_9 + cidade_10 + cidade_11 + cidade_12 +  cidade_13+ cidade_14+ cidade_15+ cidade_16+ cidade_17,
     data = vendas_dummies)</code></pre>
<p>Ao criar variáveis <em>dummies</em> é necessário verificar se uma ou mais destas variáveis possuem significância estatística, para isso usamos o comando summarypara verificar o <em>p-value</em> de cada um, toda variável com p-value maior que 0,05 deve ser removida do modelo</p>
<pre class="code"><code class="hljs"><span class="hljs-title function_">summary</span>(ols_final_dummies)</code></pre>
<pre class="code"><code class="hljs">
<span class="hljs-comment">## Call:</span>
<span class="hljs-comment">## lm(formula = receita ~ nps + inflacao + cidade_2 + cidade_3 + </span>
<span class="hljs-comment">##     cidade_4 + cidade_5 + cidade_6 + cidade_7 + cidade_8 + cidade_9 + </span>
<span class="hljs-comment">##     cidade_10 + cidade_11 + cidade_12 + cidade_13 + cidade_14 + </span>
<span class="hljs-comment">##     cidade_15 + cidade_16 + cidade_17, data = vendas_dummies)</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">## Residuals:</span>
<span class="hljs-comment">##      Min       1Q   Median       3Q      Max </span>
<span class="hljs-comment">## -2514.31  -140.56     8.63   151.16  1333.93 </span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">## Coefficients: (1 not defined because of singularities)</span>
<span class="hljs-comment">##               Estimate Std. Error t value Pr(&gt;|t|)    </span>
<span class="hljs-comment">## (Intercept) -1.344e+04  1.083e+03 -12.412  &lt; 2e-16 ***</span>
<span class="hljs-comment">## nps          2.852e+01  8.283e-01  34.426  &lt; 2e-16 ***</span>
<span class="hljs-comment">## inflacao     1.270e+05  1.026e+04  12.377  &lt; 2e-16 ***</span>
<span class="hljs-comment">## cidade_2     1.896e+01  1.102e+02   0.172   0.8634    </span>
<span class="hljs-comment">## cidade_3    -9.563e+01  1.103e+02  -0.867   0.3862    </span>
<span class="hljs-comment">## cidade_4    -4.043e+02  8.725e+01  -4.634 4.11e-06 ***</span>
<span class="hljs-comment">## cidade_5     3.096e+02  1.257e+02   2.464   0.0139 *  </span>
<span class="hljs-comment">## cidade_6     6.555e+01  6.813e+01   0.962   0.3362    </span>
<span class="hljs-comment">## cidade_7     2.746e+01  7.334e+01   0.374   0.7082    </span>
<span class="hljs-comment">## cidade_8    -1.934e+03  2.371e+02  -8.157 1.14e-15 ***</span>
<span class="hljs-comment">## cidade_9     9.821e+02  2.005e+02   4.899 1.14e-06 ***</span>
<span class="hljs-comment">## cidade_10   -7.141e+02  5.836e+01 -12.236  &lt; 2e-16 ***</span>
<span class="hljs-comment">## cidade_11   -1.409e+02  6.263e+01  -2.249   0.0247 *  </span>
<span class="hljs-comment">## cidade_12    5.940e+01  1.118e+02   0.531   0.5954    </span>
<span class="hljs-comment">## cidade_13   -1.421e+02  1.131e+02  -1.256   0.2093    </span>
<span class="hljs-comment">## cidade_14   -9.191e+02  1.178e+02  -7.799 1.71e-14 ***</span>
<span class="hljs-comment">## cidade_15    1.874e+03  2.508e+02   7.470 1.89e-13 ***</span>
<span class="hljs-comment">## cidade_16    3.923e+02  8.171e+01   4.801 1.84e-06 ***</span>
<span class="hljs-comment">## cidade_17           NA         NA      NA       NA    </span>
<span class="hljs-comment">## ---</span>
<span class="hljs-comment">## Signif. codes:  0 &#x27;***&#x27; 0.001 &#x27;**&#x27; 0.01 &#x27;*&#x27; 0.05 &#x27;.&#x27; 0.1 &#x27; &#x27; 1</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">## Residual standard error: 332.2 on 906 degrees of freedom</span>
<span class="hljs-comment">## Multiple R-squared:  0.8843, Adjusted R-squared:  0.8821 </span>
<span class="hljs-comment">## F-statistic: 407.3 on 17 and 906 DF,  p-value: &lt; 2.2e-16</span></code></pre>
<p>Para fazer a remoção destas variáveis podemos utilizar o método <em>stepwise</em>, que fará a remoção e recalculará o modelo apenas com aquelas variáveis que possuem a capacidade de explicar o modelo</p>
<pre class="code"><code class="hljs">ols_final_dummies_step = 
  <span class="hljs-title function_">step</span>(object = ols_final_dummies,
       step = <span class="hljs-title function_">qchisq</span>(p = <span class="hljs-number">0.05</span>, df = <span class="hljs-number">1</span>,lower.tail = FALSE))</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">## Start:  AIC=10746.98</span>
<span class="hljs-comment">## receita ~ nps + inflacao + cidade_2 + cidade_3 + cidade_4 + cidade_5 + </span>
<span class="hljs-comment">##     cidade_6 + cidade_7 + cidade_8 + cidade_9 + cidade_10 + cidade_11 + </span>
<span class="hljs-comment">##     cidade_12 + cidade_13 + cidade_14 + cidade_15 + cidade_16 + </span>
<span class="hljs-comment">##     cidade_17</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">## Step:  AIC=10746.98</span>
<span class="hljs-comment">## receita ~ nps + inflacao + cidade_2 + cidade_3 + cidade_4 + cidade_5 + </span>
<span class="hljs-comment">##     cidade_6 + cidade_7 + cidade_8 + cidade_9 + cidade_10 + cidade_11 + </span>
<span class="hljs-comment">##     cidade_12 + cidade_13 + cidade_14 + cidade_15 + cidade_16</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">##             Df Sum of Sq       RSS   AIC</span>
<span class="hljs-comment">## - cidade_2   1      3270 100003054 10745</span>
<span class="hljs-comment">## - cidade_7   1     15473 100015257 10745</span>
<span class="hljs-comment">## - cidade_12  1     31152 100030936 10745</span>
<span class="hljs-comment">## - cidade_3   1     82951 100082735 10746</span>
<span class="hljs-comment">## - cidade_6   1    102172 100101956 10746</span>
<span class="hljs-comment">## - cidade_13  1    174243 100174027 10747</span>
<span class="hljs-comment">## &lt;none&gt;                    99999784 10747</span>
<span class="hljs-comment">## - cidade_11  1    558331 100558114 10750</span>
<span class="hljs-comment">## - cidade_5   1    669874 100669658 10751</span>
<span class="hljs-comment">## - cidade_4   1   2370248 102370031 10767</span>
<span class="hljs-comment">## - cidade_16  1   2544440 102544224 10768</span>
<span class="hljs-comment">## - cidade_9   1   2648615 102648399 10769</span>
<span class="hljs-comment">## - cidade_15  1   6158538 106158321 10800</span>
<span class="hljs-comment">## - cidade_14  1   6714231 106714015 10805</span>
<span class="hljs-comment">## - cidade_8   1   7343946 107343730 10810</span>
<span class="hljs-comment">## - cidade_10  1  16525380 116525163 10886</span>
<span class="hljs-comment">## - inflacao   1  16909397 116909180 10889</span>
<span class="hljs-comment">## - nps        1 130813027 230812811 11518</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">## Step:  AIC=10745.01</span>
<span class="hljs-comment">## receita ~ nps + inflacao + cidade_3 + cidade_4 + cidade_5 + cidade_6 + </span>
<span class="hljs-comment">##     cidade_7 + cidade_8 + cidade_9 + cidade_10 + cidade_11 + </span>
<span class="hljs-comment">##     cidade_12 + cidade_13 + cidade_14 + cidade_15 + cidade_16</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">##             Df Sum of Sq       RSS   AIC</span>
<span class="hljs-comment">## - cidade_7   1     20346 100023400 10743</span>
<span class="hljs-comment">## - cidade_12  1     41780 100044834 10743</span>
<span class="hljs-comment">## - cidade_3   1    113279 100116333 10744</span>
<span class="hljs-comment">## - cidade_6   1    118867 100121921 10744</span>
<span class="hljs-comment">## &lt;none&gt;                   100003054 10745</span>
<span class="hljs-comment">## - cidade_13  1    284689 100287743 10746</span>
<span class="hljs-comment">## - cidade_11  1    603296 100606350 10749</span>
<span class="hljs-comment">## - cidade_5   1   2096269 102099323 10762</span>
<span class="hljs-comment">## - cidade_4   1   2767891 102770945 10768</span>
<span class="hljs-comment">## - cidade_16  1   4742302 104745356 10786</span>
<span class="hljs-comment">## - cidade_9   1   9452588 109455642 10826</span>
<span class="hljs-comment">## - cidade_14  1  10763230 110766284 10838</span>
<span class="hljs-comment">## - cidade_10  1  16601943 116604997 10885</span>
<span class="hljs-comment">## - cidade_8   1  18475157 118478211 10900</span>
<span class="hljs-comment">## - cidade_15  1  21443025 121446079 10922</span>
<span class="hljs-comment">## - inflacao   1  56343070 156346124 11156</span>
<span class="hljs-comment">## - nps        1 130824194 230827247 11516</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">## Step:  AIC=10743.2</span>
<span class="hljs-comment">## receita ~ nps + inflacao + cidade_3 + cidade_4 + cidade_5 + cidade_6 + </span>
<span class="hljs-comment">##     cidade_8 + cidade_9 + cidade_10 + cidade_11 + cidade_12 + </span>
<span class="hljs-comment">##     cidade_13 + cidade_14 + cidade_15 + cidade_16</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">##             Df Sum of Sq       RSS   AIC</span>
<span class="hljs-comment">## - cidade_12  1     46998 100070398 10742</span>
<span class="hljs-comment">## - cidade_6   1    110240 100133639 10742</span>
<span class="hljs-comment">## - cidade_3   1    186673 100210073 10743</span>
<span class="hljs-comment">## &lt;none&gt;                   100023400 10743</span>
<span class="hljs-comment">## - cidade_13  1    438006 100461406 10745</span>
<span class="hljs-comment">## - cidade_11  1    671247 100694647 10747</span>
<span class="hljs-comment">## - cidade_5   1   2230779 102254178 10762</span>
<span class="hljs-comment">## - cidade_4   1   3210063 103233463 10770</span>
<span class="hljs-comment">## - cidade_16  1   4734930 104758330 10784</span>
<span class="hljs-comment">## - cidade_9   1  10430538 110453938 10833</span>
<span class="hljs-comment">## - cidade_14  1  12824578 112847978 10853</span>
<span class="hljs-comment">## - cidade_10  1  18406072 118429472 10897</span>
<span class="hljs-comment">## - cidade_8   1  23029683 123053083 10933</span>
<span class="hljs-comment">## - cidade_15  1  23793717 123817117 10938</span>
<span class="hljs-comment">## - inflacao   1  67164122 167187522 11216</span>
<span class="hljs-comment">## - nps        1 130943242 230966641 11514</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">## Step:  AIC=10741.63</span>
<span class="hljs-comment">## receita ~ nps + inflacao + cidade_3 + cidade_4 + cidade_5 + cidade_6 + </span>
<span class="hljs-comment">##     cidade_8 + cidade_9 + cidade_10 + cidade_11 + cidade_13 + </span>
<span class="hljs-comment">##     cidade_14 + cidade_15 + cidade_16</span></code></pre>
<p>Vamos ver como ficou o BIC</p>
<pre class="code"><code class="hljs">BIC(ols_final_dummies_step)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">## [1] 13443.09</span></code></pre>
<p>Para finalizar vamos comparar o modelo final com o modelo OLS com variáveis <em>dummies</em> e <em>stepwise</em>:</p>
<pre class="code"><code class="hljs">teste_dummies <span class="hljs-operator">=</span>
    dummy_cols(.data <span class="hljs-operator">=</span> teste,
               select_columns <span class="hljs-operator">=</span> &quot;cidade&quot;,
               remove_first_dummy <span class="hljs-operator">=</span> <span class="hljs-literal">TRUE</span>,
               remove_selected_columns <span class="hljs-operator">=</span> <span class="hljs-literal">TRUE</span>)</code></pre>
<pre class="code"><code class="hljs">teste_dummies<span class="hljs-operator">$</span>cidade_2 <span class="hljs-operator">=</span> <span class="hljs-literal">NULL</span>
teste_dummies<span class="hljs-operator">$</span>cidade_7 <span class="hljs-operator">=</span> <span class="hljs-literal">NULL</span>
teste_dummies<span class="hljs-operator">$</span>cidade_12 <span class="hljs-operator">=</span> <span class="hljs-literal">NULL</span>
teste_dummies<span class="hljs-operator">$</span>cidade_17 <span class="hljs-operator">=</span> <span class="hljs-literal">NULL</span></code></pre>
<pre class="code"><code class="hljs">teste$ols_completo_fitted = 
   <span class="hljs-title function_">predict</span>(ols_final_dummies_step, teste_dummies)</code></pre>
<pre class="code"><code class="hljs">teste %&gt;%
  <span class="hljs-title function_">ggplot</span>() +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y = hlm_final_fitted, color = <span class="hljs-string">&quot;1 - HLM Modelo Final&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y= ols_completo_fitted, color = <span class="hljs-string">&quot;2 - OLS c/ Dummies e Stepwise&quot;</span>),
              method = <span class="hljs-string">&quot;lm&quot;</span>, se = F, formula = y ~ splines::<span class="hljs-title function_">bs</span>(x, df = <span class="hljs-number">5</span>),
              size = <span class="hljs-number">1.5</span>) +
  <span class="hljs-title function_">geom_smooth</span>(<span class="hljs-title function_">aes</span>(x = receita, y = receita), method = <span class="hljs-string">&quot;lm&quot;</span>, 
              color = <span class="hljs-string">&quot;gray44&quot;</span>, size = <span class="hljs-number">1.05</span>,
              linetype = <span class="hljs-string">&quot;longdash&quot;</span>) +
  <span class="hljs-title function_">scale_color_manual</span>(<span class="hljs-string">&quot;Modelos:&quot;</span>, 
                     values = <span class="hljs-title function_">c</span>(<span class="hljs-string">&quot;deepskyblue1&quot;</span>, <span class="hljs-string">&quot;maroon1&quot;</span>)) +
  <span class="hljs-title function_">labs</span>(x = <span class="hljs-string">&quot;Receita Real&quot;</span>, y = <span class="hljs-string">&quot;Receita Prevista&quot;</span>) +
  <span class="hljs-title function_">theme_bw</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2F235341f7cd59b77d.png?alt=media&amp;token=ec73c9c8-b4a5-47a3-b3bf-b35fd659c238" alt="" loading="lazy" decoding="async">
<h2 id="conclusao">Conclusão</h2>
<p>A regressão multinível é capaz de considerar melhor todas os aspectos dos dados de treino do modelo, criando um modelo capaz de prever com maior exatidão valores futuros.</p>
<p>Uma outra forma de verificar a qualidade do modelo é através da verificação da raiz quadrada do erro médio (RMSE em inglês), uma métrica utilizada para comparar modelos indicando sua acuracidade (quando menor seu valor melhor o resultado) e reforça a capacidade do modelo multinível em prever resultados com menor erro, neste caso ele é <strong>5x mais eficiente que o modelo tradicional.</strong></p>
<pre class="code"><code class="hljs">teste %&gt;% 
  
  <span class="hljs-title function_">summarise</span>(hlm = <span class="hljs-title function_">sqrt</span>(<span class="hljs-title function_">mean</span>((receita - hlm_final_fitted) ^ <span class="hljs-number">2</span>,na.rm = T)),
            ols = <span class="hljs-title function_">sqrt</span>(<span class="hljs-title function_">mean</span>((receita - ols_completo_fitted) ^ <span class="hljs-number">2</span>,na.rm = T))) %&gt;%
  <span class="hljs-title function_">melt</span>() %&gt;%
  <span class="hljs-title function_">ggplot</span>(<span class="hljs-title function_">aes</span>(y = value, x=variable, fill = <span class="hljs-title function_">factor</span>(variable))) +
  <span class="hljs-title function_">geom_bar</span>(stat = <span class="hljs-string">&quot;identity&quot;</span>) + 
  <span class="hljs-title function_">geom_label</span>(<span class="hljs-title function_">aes</span>(label = (<span class="hljs-title function_">round</span>(value,<span class="hljs-number">3</span>))), hjust = <span class="hljs-number">1.2</span>, color = <span class="hljs-string">&quot;white&quot;</span>, size = <span class="hljs-number">5</span>) +
  <span class="hljs-title function_">coord_flip</span>() +
  <span class="hljs-title function_">labs</span>(title=<span class="hljs-string">&quot;RMSE&quot;</span>, 
       x = <span class="hljs-string">&quot;modelos&quot;</span>,
       y = <span class="hljs-string">&quot;&quot;</span>) + 
  <span class="hljs-title function_">theme_minimal</span>()</code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-g3IDlm72dZid_%2Fcontent%2F3d84bd9d23b2a902.png?alt=media&amp;token=0b4194a4-460e-4cbf-ab9d-6e500434af8c" alt="" loading="lazy" decoding="async">
<p>Infelizmente desta vez eu não posso divulgar os dados originais, mas com este mesmo código, apenas substituindo as variáveis receita, NPS, inflação e cidade é possível aplicá-la a diversos cenários de dados.</p>
<p>Caso encontre alguma falha nos algoritmos ou um erro no processo, por favor me avise no meu linkedin (<a href="https://www.linkedin.com/in/marcosmhs/" target="_blank" rel="noopener">https://www.linkedin.com/in/marcosmhs/</a>) e ficarei feliz realizar as correções necessárias e incluí-lo neste texto.</p>
<p>Até a próxima!</p>
]]></content:encoded>
  </item>
  <item>
    <title>Random Forest 101 utilizando R</title>
    <link>https://www.marcosmhs.com.br/artigos/random-forest-101-utilizando-r/</link>
    <guid isPermaLink="true">https://www.marcosmhs.com.br/artigos/random-forest-101-utilizando-r/</guid>
    <pubDate>Mon, 20 Jun 2022 14:37:22 GMT</pubDate>
    <dc:creator>Marcos H. Silva</dc:creator>
    <category>RStudio</category>
    <category>Randon Forest</category>
    <description>O texto de hoje é sobre um dos modelos preditivos mais relevantes atualmente capaz de rivalizar com redes neurais complexas e que deixa muitos modelos de…</description>
    <content:encoded><![CDATA[<figure><img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-lCooZY9x-2wAw%2Fcontent%2F1fac91c9d5dcf679.jpg?alt=media&amp;token=9216af36-77e0-4304-abcd-3df37cdf12f2" alt="Photo by Colin Watts on Unsplash" loading="lazy" decoding="async"><figcaption>Photo by Colin Watts on Unsplash</figcaption></figure>
<h3 id="uma-introducao-sobre-o-time">Uma introdução sobre o time</h3>
<p>O texto de hoje é sobre um dos modelos preditivos mais relevantes atualmente capaz de rivalizar com redes neurais complexas e que deixa muitos modelos de regressão linear no chinelo! Hoje vamos de Floretas Aleatórias! (Mais um exemplo de como a tradução direta do inglês para o português é complicado!).</p>
<p>Este tipo de algoritmo de machine learning se mostra excepcionalmente relevante em problemas de classificação, quando o resultado esperado não é um valor numérico, mas uma informação categórica, vulgo qualitativa.</p>
<p>O nome (esquisito em português) vem de sua base, as árvores de decisão, e utilizando uma série de regras de separação dos dados estas “florestas” são capazes de predições altamente acuradas.</p>
<p>Falando rapidamente das árvores de decisão, elas apresentam uma forma simples de classificação, separando as informações em galhos até chegar em um nível onde a informação não pode mais ser segmentada. Um exemplo lúdico, pode ser aquela brincadeira da adivinhação, onde você começa perguntando: “Sou um animal ou uma pessoa”, “Sou homem ou mulher”, “Sou uma criança ou um adulto?” e através destas perguntas você começa a estreitar as opções até chegar no melhor resultado possível, se fosse uma brinca com meu filho este resultado geralmente é Homem Aranha!</p>
<p>Cada pergunta desta pode ser comparada aos galhos de uma árvore de decisão e as folhas, seu nível mais baixo são as respostas possíveis. Abaixo uma representação de uma árvore de decisão olhando para os dados criada com base nos dados que exploraremos daqui a pouco!</p>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-lCooZY9x-2wAw%2Fcontent%2F92ca9dcd1f8a53bf.png?alt=media&amp;token=a022ed4a-ae5c-49d9-a0a5-8d42c0994ab5" alt="" loading="lazy" decoding="async">
<p>Caso queira se aprofundar um pouco mais no tema, deixo o <a href="https://medium.com/@gabriel.stankevix/arvore-de-decis%C3%A3o-em-r-85a449b296b2" target="_blank" rel="noopener">texto</a> do Gabriel Stankevix aqui do blog Medium, que possui uma infinidade de conteúdos interessantes sobre data science e machine learning.</p>
<p>As random forests se apoiam nas árvores de decisão criando centenas de versões diferentes destas árvores com base nos dados e nas variáveis informadas. Para isso elas utilizam:</p>
<p><em><strong>Seleção aleatória dos dados</strong></em><em>: de forma geral 2/3 dos dados informados serão selecionados de forma aleatória para serem utilizados na etapa de aprendizagem e o outro 1/3 será utilizado para validar o resultado de cada uma das árvores de decisão criadas.</em></p>
<p><em><strong>Grande número de árvores</strong></em><em>: no mundo real, quanto maior uma floresta melhor para nós e no caso das random forests geralmente se trabalha com centenas arvores de decisão, não há um número padrão embora a maior parte dos exemplos encontrados trabalham com 500 árvores por modelo. Cada uma receberá uma amostra aleatória dos dados e fará predições baseadas nestas informações</em></p>
<p><em><strong>Seleção aleatória de variáveis</strong></em><em>: à cada execução de uma árvore um número aleatório de variáveis de sua base de dados é selecionado para ser utilizado. Este número é calculado de acordo com a quantidade total de colunas que forem informadas na criação do modelo.</em></p>
<p><em><strong>Resultado baseado na média de acerto de cada árvore</strong></em><em>: ao final da execução do algoritmo é feita uma média da taxa de acerto de cada uma das centenas de árvores de decisão e das variáveis utilizadas em cada uma, com este resultado as melhores árvores serão utilizadas para os cálculos de predição bem como as variáveis classificadas de acordo com sua utilização taxa de assertividade.</em></p>
<p>Para ficar mais claro, nada melhor que um exemplo escrito em R :)</p>
<pre class="code"><code class="hljs">pacotes &lt;- <span class="hljs-title function_">c</span>(<span class="hljs-string">&quot;stringr&quot;</span>,<span class="hljs-string">&quot;tidyr&quot;</span>,<span class="hljs-string">&quot;ggplot2&quot;</span>, <span class="hljs-string">&quot;plotly&quot;</span>, <span class="hljs-string">&quot;dplyr&quot;</span>, <span class="hljs-string">&quot;randomForest&quot;</span>, <span class="hljs-string">&quot;caTools&quot;</span>, <span class="hljs-string">&quot;data.table&quot;</span>, <span class="hljs-string">&quot;kableExtra&quot;</span>, <span class="hljs-string">&quot;caret&quot;</span>, <span class="hljs-string">&quot;rpart&quot;</span>, <span class="hljs-string">&quot;rpart.plot&quot;</span>, <span class="hljs-string">&quot;funModeling&quot;</span>, <span class="hljs-string">&quot;janitor&quot;</span>)

<span class="hljs-keyword">if</span>(<span class="hljs-title function_">sum</span>(<span class="hljs-keyword">as</span>.<span class="hljs-title function_">numeric</span>(!pacotes %<span class="hljs-keyword">in</span>% installed.<span class="hljs-title function_">packages</span>())) != <span class="hljs-number">0</span>){
  instalador &lt;- pacotes[!pacotes %<span class="hljs-keyword">in</span>% installed.<span class="hljs-title function_">packages</span>()]
  <span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:<span class="hljs-title function_">length</span>(instalador)) {
    install.<span class="hljs-title function_">packages</span>(instalador, dependencies = T)
    <span class="hljs-title function_">break</span>()}
  <span class="hljs-title function_">sapply</span>(pacotes, require, character = T) 
} <span class="hljs-keyword">else</span> {
  <span class="hljs-title function_">sapply</span>(pacotes, require, character = T) 
}</code></pre>
<p>Para este exemplo, utilizarei uma base de dados (<a href="https://www.kaggle.com/datasets/fedesoriano/stroke-prediction-dataset" target="_blank" rel="noopener">disponível no Kaggle</a>) com 11 informações diferentes de 4909 pacientes indicando aqueles que tiveram e não tiveram um ataque do coração.</p>
<p>Para sua utilização foi necessário transformar as variáveis categóricas em fatores e remover a coluna ID, que não será utilizada em nossa análise. Também foram removidas todas as linhas que possuíam alguma informação em branco.</p>
<pre class="code"><code class="hljs">dados = 
  <span class="hljs-title function_">fread</span>(<span class="hljs-string">&quot;dataset-stroke-data.csv&quot;</span>, header = T) %&gt;%
  <span class="hljs-title function_">select</span>(<span class="hljs-title function_">everything</span>(), -id) %&gt;%
  <span class="hljs-title function_">mutate</span>(
    hypertension = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(hypertension),
    heart_disease = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(heart_disease),
    smoking_status = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(smoking_status),
    Residence_type = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(Residence_type),
    work_type = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(work_type),
    ever_married = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(ever_married),
    bmi = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">numeric</span>(<span class="hljs-title function_">ifelse</span>(bmi == <span class="hljs-string">&quot;N/A&quot;</span>, NA, bmi)),
    stroke = <span class="hljs-keyword">as</span>.<span class="hljs-title function_">factor</span>(<span class="hljs-title function_">ifelse</span>(stroke==<span class="hljs-number">0</span>, <span class="hljs-string">&quot;N&quot;</span>, <span class="hljs-string">&quot;Y&quot;</span>))) %&gt;%
  drop_na

<span class="hljs-title function_">summary</span>(dados)</code></pre>
<pre class="code"><code class="hljs">##     gender               age        hypertension heart_disease ever_married
##  <span class="hljs-title class_">Length</span>:<span class="hljs-number">4909</span>        <span class="hljs-title class_">Min</span>.   : <span class="hljs-number">0.08</span>   <span class="hljs-number">0</span>:<span class="hljs-number">4458</span>       <span class="hljs-number">0</span>:<span class="hljs-number">4666</span>        <span class="hljs-title class_">No</span> :<span class="hljs-number">1705</span>    
##  <span class="hljs-title class_">Class</span> :character   1st <span class="hljs-title class_">Qu</span>.:<span class="hljs-number">25.00</span>   <span class="hljs-number">1</span>: <span class="hljs-number">451</span>       <span class="hljs-number">1</span>: <span class="hljs-number">243</span>        <span class="hljs-title class_">Yes</span>:<span class="hljs-number">3204</span>    
##  <span class="hljs-title class_">Mode</span>  :character   <span class="hljs-title class_">Median</span> :<span class="hljs-number">44.00</span>                                          
##                     <span class="hljs-title class_">Mean</span>   :<span class="hljs-number">42.87</span>                                          
##                     3rd <span class="hljs-title class_">Qu</span>.:<span class="hljs-number">60.00</span>                                          
##                     <span class="hljs-title class_">Max</span>.   :<span class="hljs-number">82.00</span>                                          
##          work_type    Residence_type avg_glucose_level      bmi       
##  children     : <span class="hljs-number">671</span>   <span class="hljs-title class_">Rural</span>:<span class="hljs-number">2419</span>     <span class="hljs-title class_">Min</span>.   : <span class="hljs-number">55.12</span>    <span class="hljs-title class_">Min</span>.   :<span class="hljs-number">10.30</span>  
##  Govt_job     : <span class="hljs-number">630</span>   <span class="hljs-title class_">Urban</span>:<span class="hljs-number">2490</span>     1st <span class="hljs-title class_">Qu</span>.: <span class="hljs-number">77.07</span>    1st <span class="hljs-title class_">Qu</span>.:<span class="hljs-number">23.50</span>  
##  Never_worked :  <span class="hljs-number">22</span>                  <span class="hljs-title class_">Median</span> : <span class="hljs-number">91.68</span>    <span class="hljs-title class_">Median</span> :<span class="hljs-number">28.10</span>  
##  <span class="hljs-title class_">Private</span>      :<span class="hljs-number">2811</span>                  <span class="hljs-title class_">Mean</span>   :<span class="hljs-number">105.31</span>    <span class="hljs-title class_">Mean</span>   :<span class="hljs-number">28.89</span>  
##  <span class="hljs-title class_">Self</span>-employed: <span class="hljs-number">775</span>                  3rd <span class="hljs-title class_">Qu</span>.:<span class="hljs-number">113.57</span>    3rd <span class="hljs-title class_">Qu</span>.:<span class="hljs-number">33.10</span>  
##                                      <span class="hljs-title class_">Max</span>.   :<span class="hljs-number">271.74</span>    <span class="hljs-title class_">Max</span>.   :<span class="hljs-number">97.60</span>  
##          smoking_status stroke  
##  formerly smoked: <span class="hljs-number">837</span>   N:<span class="hljs-number">4700</span>  
##  never smoked   :<span class="hljs-number">1852</span>   Y: <span class="hljs-number">209</span>  
##  smokes         : <span class="hljs-number">737</span>           
##  <span class="hljs-title class_">Unknown</span>        :<span class="hljs-number">1483</span>           
##                                 
##</code></pre>
<p>Vamos fazer uma análise exploratória dos dados e verificar se temos alguma informação inconsistente em nossas variáveis categóricas</p>
<pre class="code"><code class="hljs">#<span class="hljs-title class_">Sele</span>ção <span class="hljs-keyword">do</span> nome das variáveis categóricas
dados %&gt;% 
  <span class="hljs-title function_">select_if</span>(<span class="hljs-keyword">is</span>.factor) %&gt;% 
  <span class="hljs-title function_">names</span>()</code></pre>
<pre class="code"><code class="hljs">## [<span class="hljs-number">1</span>] <span class="hljs-string">&quot;hypertension&quot;</span>   <span class="hljs-string">&quot;heart_disease&quot;</span>  <span class="hljs-string">&quot;ever_married&quot;</span>   <span class="hljs-string">&quot;work_type&quot;</span>     
## [<span class="hljs-number">5</span>] <span class="hljs-string">&quot;Residence_type&quot;</span> <span class="hljs-string">&quot;smoking_status&quot;</span> <span class="hljs-string">&quot;stroke&quot;</span></code></pre>
<pre class="code"><code class="hljs">dados %&gt;% <span class="hljs-title function_">tabyl</span>(hypertension) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))
##  hypertension    n percent
##             <span class="hljs-number">0</span> <span class="hljs-number">4458</span>   <span class="hljs-number">90.8</span>%
##             <span class="hljs-number">1</span>  <span class="hljs-number">451</span>    <span class="hljs-number">9.2</span>%</code></pre>
<pre class="code"><code class="hljs">dados %&gt;% <span class="hljs-title function_">tabyl</span>(heart_disease) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))
##  heart_disease    n percent
##              <span class="hljs-number">0</span> <span class="hljs-number">4666</span>   <span class="hljs-number">95.0</span>%
##              <span class="hljs-number">1</span>  <span class="hljs-number">243</span>    <span class="hljs-number">5.0</span>%</code></pre>
<pre class="code"><code class="hljs">dados %&gt;% <span class="hljs-title function_">tabyl</span>(ever_married) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))
##  ever_married    n percent
##           <span class="hljs-title class_">Yes</span> <span class="hljs-number">3204</span>   <span class="hljs-number">65.3</span>%
##            <span class="hljs-title class_">No</span> <span class="hljs-number">1705</span>   <span class="hljs-number">34.7</span>%</code></pre>
<pre class="code"><code class="hljs">dados %&gt;% <span class="hljs-title function_">tabyl</span>(Residence_type) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))
##  Residence_type    n percent
##           <span class="hljs-title class_">Urban</span> <span class="hljs-number">2490</span>   <span class="hljs-number">50.7</span>%
##           <span class="hljs-title class_">Rural</span> <span class="hljs-number">2419</span>   <span class="hljs-number">49.3</span>%</code></pre>
<pre class="code"><code class="hljs">dados <span class="hljs-operator">%&gt;%</span> tabyl<span class="hljs-punctuation">(</span>smoking_status<span class="hljs-punctuation">)</span> <span class="hljs-operator">%&gt;%</span> adorn_pct_formatting<span class="hljs-punctuation">(</span><span class="hljs-punctuation">)</span> <span class="hljs-operator">%&gt;%</span> arrange<span class="hljs-punctuation">(</span>desc<span class="hljs-punctuation">(</span>n<span class="hljs-punctuation">)</span><span class="hljs-punctuation">)</span>
<span class="hljs-comment">##   smoking_status    n percent</span>
<span class="hljs-comment">##     never smoked 1852   37.7%</span>
<span class="hljs-comment">##          Unknown 1483   30.2%</span>
<span class="hljs-comment">##  formerly smoked  837   17.1%</span>
<span class="hljs-comment">##           smokes  737   15.0%</span></code></pre>
<pre class="code"><code class="hljs">dados %&gt;% <span class="hljs-title function_">tabyl</span>(stroke) %&gt;% <span class="hljs-title function_">adorn_pct_formatting</span>() %&gt;% <span class="hljs-title function_">arrange</span>(<span class="hljs-title function_">desc</span>(n))
##  stroke    n percent
##       N <span class="hljs-number">4700</span>   <span class="hljs-number">95.7</span>%
##       Y  <span class="hljs-number">209</span>    <span class="hljs-number">4.3</span>%</code></pre>
<pre class="code"><code class="hljs">dados <span class="hljs-operator">%&gt;%</span> tabyl<span class="hljs-punctuation">(</span>work_type<span class="hljs-punctuation">)</span> <span class="hljs-operator">%&gt;%</span> adorn_pct_formatting<span class="hljs-punctuation">(</span><span class="hljs-punctuation">)</span> <span class="hljs-operator">%&gt;%</span> arrange<span class="hljs-punctuation">(</span>desc<span class="hljs-punctuation">(</span>n<span class="hljs-punctuation">)</span><span class="hljs-punctuation">)</span>
<span class="hljs-comment">##      work_type    n percent</span>
<span class="hljs-comment">##        Private 2811   57.3%</span>
<span class="hljs-comment">##  Self-employed  775   15.8%</span>
<span class="hljs-comment">##       children  671   13.7%</span>
<span class="hljs-comment">##       Govt_job  630   12.8%</span>
<span class="hljs-comment">##   Never_worked   22    0.4%</span></code></pre>
<p>A variável work_typepossui valores relativamente bem distribuídos, com exceção das pessoas que nunca trabalharam (Never_worked), com apenas 22 registros ou 0.04% de toda a base. Vamos optar pela remoção destes registros para reduzir a quantidade de categorias de nossa base, dado que representam um percentual muito pequeno de dados.</p>
<pre class="code"><code class="hljs">dados = 
  dados %&gt;%
  <span class="hljs-built_in">filter</span>(work_type != <span class="hljs-string">&quot;Never_worked&quot;</span>)</code></pre>
<p>Uma vez que temos nossa base pronta, seguiremos para a separação de dados para treino de nosso modelo e para testarmos sua acurácia. Mesmo que o algoritmo faça esta verificação interna utilizarei 10% da base para mostrar como ficou resultado.</p>
<pre class="code"><code class="hljs">amostra = sample.<span class="hljs-title function_">split</span>(dados$stroke, <span class="hljs-title class_">SplitRatio</span> = .<span class="hljs-number">90</span>, )

treino = <span class="hljs-title function_">subset</span>(dados, amostra == T)
teste  = <span class="hljs-title function_">subset</span>(dados, amostra == F)</code></pre>
<h2 id="a-random-forest">A random forest</h2>
<p>Embora o modelo faça o cálculo para definir a quantidade variáveis de nossa base que será usada em cada árvore, vamos fazer o cálculo do % de erro que cada combinação gera ao final de uma execução. Para isso vou utilizar o método tuneRF.</p>
<pre class="code"><code class="hljs">mtry <span class="hljs-operator">=</span> 
  tuneRF<span class="hljs-punctuation">(</span>
    <span class="hljs-comment">#lista das variáveis que serão utilizadas para a especificação do modelo</span>
    treino <span class="hljs-operator">%&gt;%</span> select<span class="hljs-punctuation">(</span><span class="hljs-operator">-</span>stroke<span class="hljs-punctuation">)</span><span class="hljs-punctuation">,</span> 
    <span class="hljs-comment"># coluna que desejamos prever</span>
    treino<span class="hljs-operator">$</span>stroke<span class="hljs-punctuation">,</span> 
    <span class="hljs-comment"># quantidade de árvores que devem ser geradas no modelo</span>
    ntreeTry<span class="hljs-operator">=</span><span class="hljs-number">500</span><span class="hljs-punctuation">,</span>
    stepFactor<span class="hljs-operator">=</span><span class="hljs-number">1.5</span><span class="hljs-punctuation">,</span>
    improve<span class="hljs-operator">=</span><span class="hljs-number">0.01</span><span class="hljs-punctuation">)</span></code></pre>
<pre class="code"><code class="hljs"><span class="hljs-built_in">print</span>(mtry)
<span class="hljs-comment">##       mtry   OOBError</span>
<span class="hljs-comment">## 2.OOB    2 0.04297408</span>
<span class="hljs-comment">## 3.OOB    3 0.04297408</span>
<span class="hljs-comment">## 4.OOB    4 0.04365621</span></code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-lCooZY9x-2wAw%2Fcontent%2Fe64ee3b39fd257a0.png?alt=media&amp;token=1e36a478-d0b5-4765-9db7-35c378791fab" alt="" loading="lazy" decoding="async">
<p>Algo importante das random foreres e de outros modelos de machine learning é que nem sempre todas as variáveis disponíveis precisam ser utilizadas, neste exemplo poderemos trabalhar com duas variáveis em cada árvore para aumentarmos a chance de um modelo eficaz.</p>
<pre class="code"><code class="hljs">modelo <span class="hljs-operator">=</span> 
  randomForest<span class="hljs-punctuation">(</span>
    <span class="hljs-comment"># a fórmula da árvore, a informação de ataque cardíaco (stroke) em função de todas as variáveis de nossa base de dados</span>
    formula <span class="hljs-operator">=</span> stroke <span class="hljs-operator">~</span> .<span class="hljs-punctuation">,</span>
    <span class="hljs-comment"># a base de treino com 4418 registros</span>
    data <span class="hljs-operator">=</span> treino<span class="hljs-punctuation">,</span> 
    <span class="hljs-comment"># quantidade de colunas que serão utilizadas em cada árvore</span>
    mtry <span class="hljs-operator">=</span> <span class="hljs-number">2</span><span class="hljs-punctuation">,</span>
    <span class="hljs-comment"># quantidade de árvores que devem ser criadas pelo algorítmo </span>
    ntree<span class="hljs-operator">=</span><span class="hljs-number">500</span><span class="hljs-punctuation">)</span></code></pre>
<p>Vamos verificar, de acordo com o modelo final quais variáveis foram mais importantes em todas as 500 combinações realizadas:</p>
<pre class="code"><code class="hljs">varImpPlot<span class="hljs-punctuation">(</span>modelo<span class="hljs-punctuation">,</span> sort <span class="hljs-operator">=</span> <span class="hljs-built_in">T</span><span class="hljs-punctuation">)</span></code></pre>
<img src="https://firebasestorage.googleapis.com/v0/b/omarcosmhs.appspot.com/o/images%2Farticles%2Ffirestore-uid-lCooZY9x-2wAw%2Fcontent%2Fee635dedcb8f6612.png?alt=media&amp;token=1b0545fe-ce10-4823-9042-4dd20c35b390" alt="" loading="lazy" decoding="async">
<p>As variáveis avg_glucose_level(média dos níveis de açúcar no sangue), age(idade) e bmi(índice de massa corporal) foram as variáveis mais relevantes enquanto a ever_married (se foi casado alguma vez a menos relevante).</p>
<p>Com o modelo criado podemos realizar a predição de resultado com base nos valores da base de teste e comparar o resultado predito com os valores reais.</p>
<pre class="code"><code class="hljs">pred = predict(modelo, teste, <span class="hljs-built_in">type</span> = <span class="hljs-string">&quot;class&quot;</span>)</code></pre>
<p>Para verificar o resultado utilizaremos uma matriz de confusão, que faz a comparação entre o real e o predito</p>
<pre class="code"><code class="hljs"><span class="hljs-title function_">confusionMatrix</span>(pred, teste$stroke)</code></pre>
<pre class="code"><code class="hljs"><span class="hljs-comment">## Confusion Matrix and Statistics</span>
<span class="hljs-comment">## </span>
<span class="hljs-comment">##           Reference</span>
<span class="hljs-comment">## Prediction   N   Y</span>
<span class="hljs-comment">##          N 468  21</span>
<span class="hljs-comment">##          Y   0   0</span>
<span class="hljs-comment">##                                           </span>
<span class="hljs-comment">##                Accuracy : 0.9571          </span>
<span class="hljs-comment">##                  95% CI : (0.9351, 0.9732)</span>
<span class="hljs-comment">##     No Information Rate : 0.9571          </span>
<span class="hljs-comment">##     P-Value [Acc &gt; NIR] : 0.5577          </span>
<span class="hljs-comment">##                                           </span>
<span class="hljs-comment">##                   Kappa : 0               </span>
<span class="hljs-comment">##                                           </span>
<span class="hljs-comment">##  Mcnemar&#x27;s Test P-Value : 1.275e-05       </span>
<span class="hljs-comment">##                                           </span>
<span class="hljs-comment">##             Sensitivity : 1.0000          </span>
<span class="hljs-comment">##             Specificity : 0.0000          </span>
<span class="hljs-comment">##          Pos Pred Value : 0.9571          </span>
<span class="hljs-comment">##          Neg Pred Value :    NaN          </span>
<span class="hljs-comment">##              Prevalence : 0.9571          </span>
<span class="hljs-comment">##          Detection Rate : 0.9571          </span>
<span class="hljs-comment">##    Detection Prevalence : 1.0000          </span>
<span class="hljs-comment">##       Balanced Accuracy : 0.5000          </span>
<span class="hljs-comment">##                                           </span>
<span class="hljs-comment">##        &#x27;Positive&#x27; Class : N               </span>
<span class="hljs-comment">##</span></code></pre>
<p>Este exemplo possui uma acurácia de 95,7%, nada mal! Mas nossa matriz de confusão não traz bons resultados!</p>
<p>Como podemos observar na imagem abaixo, vemos que na linha N e coluna N (valores preditos e reais, respectivamente) que indica pacientes que não tiveram um ataque cardíaco o modelo foi capaz de acertar os 468 registros, ou seja 100% dos casos.</p>
<p>Por outro lado, temos 21 pacientes que tiveram um ataque do coração e o modelo indicou outro resultado, por isso na coluna Y e linha Y da tabela vemos um número 0, mostrando que o modelo errou feio!</p>
<pre class="code"><code class="hljs"><span class="hljs-comment">##           Reference</span>
<span class="hljs-comment">## Prediction   N   Y</span>
<span class="hljs-comment">##          N 468  21</span>
<span class="hljs-comment">##          Y   0   0</span></code></pre>
<p>Para resolver este problema é temos alguns caminhos:</p>
<ol>
<li>rever a parametrização do algoritmo, existe um universo de opções que não foram exploradas neste texto e que podem aumentar sua acurácia</li>
<li>Aumentar a quantidade dados de treino para que o modelo possa aprender melhor com os dados históricos</li>
<li>Avaliar a substituição de variáveis, como o caso da ever_married ou inclusão de novas informações que possam ajudar na previsão de resultados</li>
</ol>
<p>Por não ser este o objetivo do texto não vamos entrar no detalhe, mas fica a sugestão de contribuição sobre o que pode ser feito para aumentar a acurácia nos casos de em que o modelo falhou e se estiver interessado podemos escrever uma versão 2.0 deste texto :)</p>
<h2 id="algumas-limitacoes">Algumas Limitações</h2>
<p>Como você viu as random forestes não são a bala de prata dos modelos preditivos e por isso é preciso considera alguns pontos de atenção ao utilizá-las:</p>
<ol>
<li>Elas não muito boas em modelos de regressão, onde o resultado esperado é um valor numérico como o valor de uma ação ou o preço da gasolina</li>
<li>Elas podem ser tendenciosas especialmente em casos em que variáveis categóricas possuem muitos valores (categorias), por exemplo, um campo de tipo de cliente que possua 10 ou mais opções, o tipo que possuir mais registros em sua base pode contaminar a predição dos demais.</li>
</ol>
<p>Mesmo com estes pontos ainda sim as random forests representam um avanço nas técnicas de machine learning e uma ferramenta incrível para a criação de modelos capazes de auxiliar na tomada de decisão.</p>
<p>Se você encontrou algum erro neste texto de conceito ou nos scripts por favor me avise através do e-mail <a href="mailto:marcosmhs@live.com">marcosmhs@live.com</a> e terei prazer em fazer a correção e incluí-lo(a) nos créditos.</p>
]]></content:encoded>
  </item>
</channel>
</rss>
