<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Paixão por Dados</title>
    <link>http://www.sillasgonzaga.com/tags/estatistica/index.xml</link>
    <description>Recent content on Paixão por Dados</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>&amp;copy; 2016. All rights reserved.</copyright>
    <atom:link href="http://www.sillasgonzaga.com/tags/estatistica/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Qual o melhor serviço de streaming de filmes e séries no Brasil? O R responde.</title>
      <link>http://www.sillasgonzaga.com/post/qual-o-melhor-servico-de-streaming/</link>
      <pubDate>Sat, 23 Feb 2019 00:00:00 +0000</pubDate>
      
      <guid>http://www.sillasgonzaga.com/post/qual-o-melhor-servico-de-streaming/</guid>
      <description>&lt;div id=&#34;introducao&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introdução&lt;/h2&gt;
&lt;p&gt;Recentemente, li um artigo sobre a &lt;a href=&#34;https://meiobit.com/397799/balcanizacao-streaming-aumento-pirataria/&#34;&gt;Balcanização dos serviços de streaming&lt;/a&gt; que me fez refletir sobre essa indústria. Dado que assinar mais de um serviço de streaming pode ser um desperdício, devido a falta de tempo para consumir tanto material, as pessoas costumam optar por apenas um dos existentes: Netflix, Amazon Prime Video ou algum outro. Como saber qual escolher?&lt;/p&gt;
&lt;p&gt;O serviço &lt;a href=&#34;https://www.justwatch.com/br/&#34;&gt;JustWatch&lt;/a&gt; ajuda um pouco. Nele, é possível pesquisar por um filme ou seriado e descobrir em quais serviços ele está disponível. Assim, se temos em mão os dados dos catálogos dos serviços, podemos avaliar a quantidade e qualidade dos filmes em cada um para decidir o melhor.&lt;/p&gt;
&lt;p&gt;Existe um &lt;a href=&#34;https://github.com/dawoudt/JustWatchAPI&#34;&gt;módulo Python&lt;/a&gt; que permite extrair os dados do JustWatch em json, tornando os dados muito fáceis para trabalhar. Por isso, este projeto usará código não só em R como em Python.&lt;/p&gt;
&lt;p&gt;Este projeto consiste em coletar os 5000 melhores filmes e seriados do IMDB, coletar dados de cada usando a API do Justwatch e analisar os resultados para concluir sobre o melhor serviço de streaming no Brasil.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;primeiro-passo-coletando-nomes-de-filmes-e-seriados&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Primeiro passo: Coletando nomes de filmes e seriados&lt;/h2&gt;
&lt;p&gt;Infelizmente, a API do Justwatch não nos permite coletar todo o catálogo do site, existindo um limite dos 1000 primeiros resultados, &lt;a href=&#34;https://github.com/dawoudt/JustWatchAPI/issues/18&#34;&gt;mesmo que se altere os parâmetros &lt;code&gt;page&lt;/code&gt; e &lt;code&gt;page_size&lt;/code&gt; da função&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Por outro lado, a função não impõe um limite de requisições feitas sequencialmente. Por isso, a melhor estratégia é iterar a função sobre uma lista de filmes a pesquisar.&lt;/p&gt;
&lt;p&gt;Onde coletar essa lista de filmes? A ideia que eu tive foi usar o IMDB para isso. Eu coletei os 5000 melhores filmes e seriados (sem distinção) para ter os resultados. Como o código é relativamente simples e os dados bem grandes, não vou descrever essa parte do projeto aqui. Os interessados podem consultar como eu fiz para coletar os dados do IMDB &lt;a href=&#34;https://gist.github.com/sillasgonzaga/565d69234f53b3aeac9e22ea7ed692b4&#34;&gt;neste gist&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;usar-o-modulo-python-para-coletar-dados-da-api-do-justwatch&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Usar o módulo Python para coletar dados da API do JustWatch&lt;/h2&gt;
&lt;p&gt;O código é bem simples: eu leio o arquivo com a lista de filmes salvos na parte anterior, itero sobre o dataframe, junto todos os resultados em um dicionário e salvo os dados em formato json.&lt;/p&gt;
&lt;p&gt;O comportamento da função &lt;code&gt;just_watch.search_for_item()&lt;/code&gt; é o mesmo de você pesquisar manualmente no site. Isto é, ao digitar na caixa de busca o título desejado, aparecerá uma lista com os resultados relacionados, sendo que provavelmente apenas o primeiro resultado é o que interessa. Por isso, no código abaixo, eu extraio o primeiro resultado da busca. Funciona na maioria das vezes.&lt;/p&gt;
&lt;pre class=&#34;python&#34;&gt;&lt;code&gt;from justwatch import JustWatch
import csv
import json
import pandas as pd
just_watch = JustWatch(country=&amp;#39;BR&amp;#39;)

# ler lista de filmes
arquivo = &amp;#39;/home/sillas/R/data/imdb/lista_filmes_imdb.csv&amp;#39;
titulos = pd.read_csv(arquivo)

out = list()

for index, row in titulos.iterrows():
    # imprimir status do loop
    if index % 100 == 0:
        print(index)
    # consultar api
    api_data = just_watch.search_for_item(query = row[&amp;quot;full_title&amp;quot;])[&amp;quot;items&amp;quot;]
    
    # salvar dados apenas se houver resultado
    if len(api_data) &amp;gt; 0:
        first_item_data = api_data[0]
        first_item_data[&amp;quot;tconst&amp;quot;] = row[&amp;quot;tconst&amp;quot;]
        out.append(first_item_data)
    
# salvar resultados em json
with open(&amp;#39;/home/sillas/R/data/imdb/justwatchdata.json&amp;#39;, &amp;#39;w&amp;#39;) as fp:
    json.dump(out, fp)
    
# salvar dados de sites de streaming
provider_details = just_watch.get_providers()

with open(&amp;#39;/home/sillas/R/data/imdb/justwatchdata_providers.json&amp;#39;, &amp;#39;w&amp;#39;) as fp:
    json.dump(provider_details, fp)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;juntando-os-dados&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Juntando os dados&lt;/h2&gt;
&lt;p&gt;Finalmente, chegamos à parte divertida. Abaixo eu importo os pacotes usados e o arquivo json salvo acima.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)
library(jsonlite)
library(UpSetR)
library(ggridges)

# gist com o json: 
jw &amp;lt;- jsonlite::fromJSON(&amp;quot;/home/sillas/R/data/imdb/justwatchdata.json&amp;quot;) %&amp;gt;% 
  as_tibble() %&amp;gt;% 
  # selecionar colunas importantes
  select(tconst, original_title, original_release_year,
         tmdb_popularity, object_type, offers, scoring) 

glimpse(jw)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Observations: 4,442
## Variables: 7
## $ tconst                &amp;lt;chr&amp;gt; &amp;quot;tt0903747&amp;quot;, &amp;quot;tt0111161&amp;quot;, &amp;quot;tt0068646&amp;quot;, &amp;quot;tt…
## $ original_title        &amp;lt;chr&amp;gt; &amp;quot;Breaking Bad&amp;quot;, &amp;quot;The Shawshank Redemption&amp;quot;…
## $ original_release_year &amp;lt;int&amp;gt; 2008, 1994, 1972, 2013, 1974, 1994, 1993, …
## $ tmdb_popularity       &amp;lt;dbl&amp;gt; 76.613, 30.009, 26.993, 82.621, 19.567, 32…
## $ object_type           &amp;lt;chr&amp;gt; &amp;quot;show&amp;quot;, &amp;quot;movie&amp;quot;, &amp;quot;movie&amp;quot;, &amp;quot;show&amp;quot;, &amp;quot;movie&amp;quot;,…
## $ offers                &amp;lt;list&amp;gt; [&amp;lt;data.frame[5 x 14]&amp;gt;, &amp;lt;data.frame[13 x 1…
## $ scoring               &amp;lt;list&amp;gt; [&amp;lt;data.frame[4 x 2]&amp;gt;, &amp;lt;data.frame[10 x 2]…&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A estrutura deste dataframe não é necessariamente tabular, como se costuma ver. As colunas &lt;code&gt;offers&lt;/code&gt; e &lt;code&gt;scoring&lt;/code&gt; são da classe &lt;code&gt;list&lt;/code&gt;, pois cada valor dessas duas variáveis é um dataframe. Ou seja, no R é possível termos dataframes dentro de um dataframe.&lt;/p&gt;
&lt;p&gt;Para tornar o dataframe mais simples de ser usado, vamos transformar essas duas colunas em dataframes separados.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# criar funcao para extrair apenas as colunas importantes de offers
extract_offers_data &amp;lt;- function(offers){
  if(!is.null(offers)){
    offers %&amp;gt;% 
      select(monetization_type, provider_id,
             date_created, presentation_type)
  }
}

tbl_offers &amp;lt;- jw %&amp;gt;% 
  select(tconst, offers) %&amp;gt;% 
  # remover filmes sem dados de streaming
  filter(!map_lgl(offers, is.null)) %&amp;gt;% 
  # usar funcao criada acima para extrair colunas
  mutate(offers = map(offers, extract_offers_data)) %&amp;gt;% 
  unnest(offers) %&amp;gt;% 
  # filtrar apenas filmes de serviços onde se paga uma taxa mensal para ter
  # acesso aos filmes, ao inves de um preço para cada filme, como se fosse
  # uma loja.
  filter(monetization_type == &amp;quot;flatrate&amp;quot;) %&amp;gt;% 
  distinct(tconst, provider_id)

tbl_scoring &amp;lt;- jw %&amp;gt;% 
  select(tconst, scoring) %&amp;gt;% 
  filter(!map_lgl(scoring, is.null)) %&amp;gt;% 
  unnest(scoring) %&amp;gt;% 
  rename(scoring_provider_type = provider_type)

# no dataframe principal, remover essas duas colunas
tbl_jw &amp;lt;- jw %&amp;gt;% 
  select(-c(offers, scoring))

# importar arquivos com os metadados dos sites de streaming
tbl_providers &amp;lt;- fromJSON(&amp;quot;/home/sillas/R/data/imdb/justwatchdata_providers.json&amp;quot;) %&amp;gt;% 
  as_tibble() %&amp;gt;%
  select(provider_id = id, provider_name = slug) %&amp;gt;% 
  mutate(provider_name = str_replace_all(provider_name, &amp;quot;-&amp;quot;, &amp;quot;_&amp;quot;))

tbl_offers_prov &amp;lt;- left_join(tbl_offers, tbl_providers, by = &amp;quot;provider_id&amp;quot;)

# criar dataset das analises
tbl_jw &amp;lt;- tbl_jw %&amp;gt;% 
  left_join(tbl_offers_prov, by = &amp;quot;tconst&amp;quot;) %&amp;gt;% 
  left_join(tbl_scoring, by = &amp;quot;tconst&amp;quot;) %&amp;gt;% 
  select(-provider_id)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Este é o dataset das nossas análises:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# dataset das analises
tbl_jw&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 41,085 x 8
##    tconst original_title original_releas… tmdb_popularity object_type
##    &amp;lt;chr&amp;gt;  &amp;lt;chr&amp;gt;                     &amp;lt;int&amp;gt;           &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;      
##  1 tt090… Breaking Bad               2008            76.6 show       
##  2 tt090… Breaking Bad               2008            76.6 show       
##  3 tt090… Breaking Bad               2008            76.6 show       
##  4 tt090… Breaking Bad               2008            76.6 show       
##  5 tt011… The Shawshank…             1994            30.0 movie      
##  6 tt011… The Shawshank…             1994            30.0 movie      
##  7 tt011… The Shawshank…             1994            30.0 movie      
##  8 tt011… The Shawshank…             1994            30.0 movie      
##  9 tt011… The Shawshank…             1994            30.0 movie      
## 10 tt011… The Shawshank…             1994            30.0 movie      
## # … with 41,075 more rows, and 3 more variables: provider_name &amp;lt;chr&amp;gt;,
## #   scoring_provider_type &amp;lt;chr&amp;gt;, value &amp;lt;dbl&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;resultados&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Resultados&lt;/h2&gt;
&lt;div id=&#34;quais-sites-possuem-mais-filmes-e-seriados&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Quais sites possuem mais filmes e seriados?&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tbl_jw %&amp;gt;% 
  distinct(tconst, object_type, provider_name) %&amp;gt;% 
  count(provider_name, object_type) %&amp;gt;% 
  group_by(object_type) %&amp;gt;% 
  mutate(pct = 100 * n/sum(n)) %&amp;gt;% 
  ggplot(aes(x = fct_rev(provider_name), y = pct)) +
  geom_col() +
  coord_flip() +
  facet_wrap(~ object_type, ncol = 1) +
  labs(x = NULL, y = &amp;quot;%&amp;quot;,
       title = &amp;quot;Presença dos melhores filmes e seriados \nnos sites de streaming no Brasil&amp;quot;) +
  theme_bw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://www.sillasgonzaga.com/post/2019-02-23-qual-o-melhor-servico-de-streaming_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Os resultados são bem interessantes. Para quem adora seriados, a Netflix reina absoluta tendo em seu portfolio 40% dos melhores seriados, enquanto que o segundo melhor neste quesito, o Amazon Prime Video, possui apenas 10%. Em termos de filmes, a Netflix também é a melhor, sendo seguida de perto pelo Telecine Play. O portfolio do Amazon Prime Video para filmes deixa bastante a desejar.&lt;/p&gt;
&lt;p&gt;Ainda sobre filmes, é bastante importante mencionar que mais da metade das produções não está disponível em nenhum serviço de streaming de vídeo por assinatura no Brasil, um resultado bem lamentável para cinéfilos.&lt;/p&gt;
&lt;p&gt;Para o restante deste post, vamos focar apenas nesses 3 principais streamings:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;prvs &amp;lt;- c(&amp;quot;netflix&amp;quot;, &amp;quot;amazon_prime_video&amp;quot;, &amp;quot;telecine_play&amp;quot;)

tbl_jw_principais &amp;lt;- tbl_jw %&amp;gt;% 
  filter(is.na(provider_name) | provider_name %in% prvs) %&amp;gt;% 
  mutate(provider_name = tidyr::replace_na(provider_name, &amp;quot;nenhum&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;quais-sites-possuem-os-filmes-mais-recentes&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Quais sites possuem os filmes mais recentes?&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;range(tbl_jw_principais$original_release_year)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 1920 2019&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tbl_jw_principais %&amp;gt;% 
  ggplot(aes(x = original_release_year, color = provider_name)) +
  stat_ecdf() +
  theme_bw() +
  scale_x_continuous(breaks = seq(1920, 2020, by  = 10), 
                     minor_breaks = NULL) +
  scale_y_continuous(breaks = seq(0, 1, .1), 
                     minor_breaks = NULL,
                     labels = scales::percent) +
  theme(legend.position = &amp;quot;bottom&amp;quot;) +
  facet_wrap(~ object_type, ncol = 2) +
  labs(title = &amp;quot;Distribuição da idade de títulos por serviço de streaming&amp;quot;,
       x = NULL, 
       y = NULL)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://www.sillasgonzaga.com/post/2019-02-23-qual-o-melhor-servico-de-streaming_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;864&#34; /&gt;&lt;/p&gt;
&lt;p&gt;O formato da curva referente à Netflix é muito interessante. Note como ela cresce numa velocidade muito maior a partir de 2010. Olhando para este ponto no eixo vertical, nota-se que 70% dos filmes e incríveis 80% dos seriados foram lançados a partir de 2010. De todos os 3 serviços de streaming, a Netflix é a mais enviesada para produções recentes. Note também como 70% dos filmes que não estão presentes em nenhum serviço por assinatura foram lançados antes de 2010. Na verdade, Netflix e Amazon Prime Video não possuem nenhum filme lançado antes de 1960.&lt;/p&gt;
&lt;p&gt;Outra maneira de visualizar os resultados acima é separando os anos por década:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tbl_jw_principais %&amp;gt;% 
  mutate(decada = as.character(round(original_release_year %/% 10) * 10)) %&amp;gt;% 
  count(decada, object_type, provider_name) %&amp;gt;% 
  ggplot(aes(x = decada, y = n, fill = provider_name)) +
  geom_col(position = position_dodge()) +
  theme_bw() +
  labs(title = &amp;quot;Quantidade de títulos por década&amp;quot;,
       x = NULL, 
       y = NULL) +
  facet_wrap(~ object_type, scales = &amp;quot;free_y&amp;quot;, ncol = 1) +
  theme(legend.position = &amp;quot;bottom&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://www.sillasgonzaga.com/post/2019-02-23-qual-o-melhor-servico-de-streaming_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;qualidade-dos-filmes&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Qualidade dos filmes&lt;/h3&gt;
&lt;p&gt;Como parâmetro para qualidade dos filmes, usei a nota do IMDB, que também é fornecida no dataset do JustWatch.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tbl_jw_principais %&amp;gt;% 
  # filtrar filmes com nota IMDB acima de 7 para eliminar entradas erradas
  filter(scoring_provider_type == &amp;quot;imdb:score&amp;quot;, value &amp;gt;= 7) %&amp;gt;% 
  mutate(value = cut(value, breaks = 0:10)) %&amp;gt;% 
  count(object_type, provider_name, value) %&amp;gt;% 
  ggplot(aes(x = value, y = n, fill = provider_name)) +
  geom_col(position = position_fill()) +
  theme_bw() +
  scale_y_continuous(breaks = seq(0, 1, .1),
                     labels = scales::percent) +
  facet_wrap(~ object_type) +
  labs(x = NULL,
       y = NULL,
       title = &amp;quot;Percentual de títulos por faixa de nota no IMDB&amp;quot;) +
  theme(legend.position = &amp;quot;bottom&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://www.sillasgonzaga.com/post/2019-02-23-qual-o-melhor-servico-de-streaming_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Não aparenta haver diferença em relação à nota dos filmes e seriados de acordo com o streaming.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;exclusividade-de-conteudo&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Exclusividade de conteúdo&lt;/h3&gt;
&lt;p&gt;Por último, mas não menos importante, existe o critério de exclusividade entre as plataformas, algo comum nesta indústria. Quantos filmes estão presentes apenas, por exemplo no Telecine Play? Quantos são possíveis de encontrar em mais de uma plataforma?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# criar matriz binaria
tbl_jw_principais_wide &amp;lt;- tbl_jw_principais %&amp;gt;% 
  distinct(tconst, provider_name) %&amp;gt;%
  mutate(provider_name = replace_na(provider_name, &amp;quot;nenhum&amp;quot;)) %&amp;gt;% 
  mutate(tem = 1) %&amp;gt;% 
  spread(provider_name, tem) %&amp;gt;% 
  mutate_at(vars(-tconst), replace_na, 0) %&amp;gt;% 
  as.data.frame()

# grafico upset
upset(tbl_jw_principais_wide, nsets = 10,
      mainbar.y.label = NULL)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://www.sillasgonzaga.com/post/2019-02-23-qual-o-melhor-servico-de-streaming_files/figure-html/unnamed-chunk-10-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Também neste quesito a Netflix é disparado o melhor dentre os 3. 979 dos títulos são exclusivos da Netflix, muito mais que a soma dos outros dois serviços. É curioso que exista pouquíssima interseção entre as plataformas: apenas 17 títulos estão presentes tanto na Netflix como no Amazon Prime Video.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;bonus-diagrama-de-venn&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Bônus: Diagrama de Venn&lt;/h3&gt;
&lt;p&gt;Outra forma de visualizar os resultados acima é por meio de um diagrama de Venn:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lst &amp;lt;- tbl_jw_principais %&amp;gt;% 
  distinct(tconst, provider_name) %&amp;gt;% 
  split(.$provider_name) %&amp;gt;% 
  map(&amp;quot;tconst&amp;quot;)

gplots::venn(lst)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://www.sillasgonzaga.com/post/2019-02-23-qual-o-melhor-servico-de-streaming_files/figure-html/unnamed-chunk-11-1.png&#34; width=&#34;864&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusao&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusão&lt;/h2&gt;
&lt;p&gt;Usando o universo dos 5000 melhores títulos de filmes e seriados de acordo com o IMDB, a Netflix é bem superior às concorrentes no Brasil.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>A equação mais perigosa do mundo e o efeito do tamanho da amostra nos resultados</title>
      <link>http://www.sillasgonzaga.com/post/a-equacao-mais-perigosa-do-mundo/</link>
      <pubDate>Sun, 01 Jul 2018 00:00:00 +0000</pubDate>
      
      <guid>http://www.sillasgonzaga.com/post/a-equacao-mais-perigosa-do-mundo/</guid>
      <description>&lt;div id=&#34;introducao&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introdução&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://old.reddit.com/r/datascience/comments/8r16mi/whats_the_dumbest_thing_a_manager_or_executive/e0np7vm/&#34;&gt;Nesta thread&lt;/a&gt; no subreddit de Data Science, um usuário fez o seguinte comentário:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So basically, I was asked to make inference on 10 people and expect those to generalize to the entire study population. I said the study was poorly designed, and that if I made up random numbers we would do a better job of understanding the customer base.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;É muito comum pessoas que não são muito familiares com conceitos de inferência estatística ignorar o fato de que tomar conclusões a partir de amostras muito pequenas pode ser bastante perigoso.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.504.3301&amp;amp;rep=rep1&amp;amp;type=pdf&#34;&gt;Neste artigo escrito por Howard Wainer&lt;/a&gt; (Aviso: Link para PDF), são citados dois motivos para que uma equação possa ser perigosa: o fato de elas serem conhecidas e o fato de elas serem desconhecidas. A equação de Moivre, que descreve o desvio padrão da distribuição amostral da média, se encontra no segundo caso:&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math inline&#34;&gt;\(\sigma_{\bar{x}}= \frac{\sigma}{\sqrt{n}}\)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Onde &lt;span class=&#34;math inline&#34;&gt;\(\sigma_{\bar{x}}\)&lt;/span&gt; é o erro padrão da média, &lt;span class=&#34;math inline&#34;&gt;\(\sigma\)&lt;/span&gt; o desvio padrão da amostra e &lt;span class=&#34;math inline&#34;&gt;\(n\)&lt;/span&gt; o tamanho da amostra. Em outras palavras, dado que &lt;span class=&#34;math inline&#34;&gt;\(\sigma\)&lt;/span&gt; é um parâmetro conhecido, quanto menor o tamanho da amost, maior será erro da estimativa, que corresponde a variação da média amostral em relação à média da população. O paper inteiro é muito bom e fácil de ler, então recomendo a leitura.&lt;/p&gt;
&lt;p&gt;O objetivo deste post é um exercício simples para mostrar o efeito do tamanho da amostra na variabilidade dos resultados, mesmo quando se sabem os valores verdadeiros dos parâmetros de toda a população.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;geracao-dos-dados-por-simulacao&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Geração dos dados por simulação&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O primeiro passo é gerar uma população de dados cujos parâmetros são conhecidos. Aqui, duas variáveis aleatórias ´x´ e ´y´ são definidas, em que x é uma variável aleatória e ´y´ deriva de x, com algum ruído:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;n &amp;lt;- 1e5
set.seed(123)
x &amp;lt;- rnorm(n, mean = 0, sd = 0.5)
y &amp;lt;- 2 * x + 5 + rnorm(n, mean = 0, sd = 0.25)

df &amp;lt;- data.frame(x = x, y = y)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mod_populacao &amp;lt;- lm(y ~ x, data = df)
summary(mod_populacao)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## 
## Call:
## lm(formula = y ~ x, data = df)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -1.0972 -0.1685 -0.0002  0.1683  1.0506 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(&amp;gt;|t|)    
## (Intercept) 5.0013045  0.0007937    6302   &amp;lt;2e-16 ***
## x           1.9986648  0.0015877    1259   &amp;lt;2e-16 ***
## ---
## Signif. codes:  0 &amp;#39;***&amp;#39; 0.001 &amp;#39;**&amp;#39; 0.01 &amp;#39;*&amp;#39; 0.05 &amp;#39;.&amp;#39; 0.1 &amp;#39; &amp;#39; 1
## 
## Residual standard error: 0.251 on 99998 degrees of freedom
## Multiple R-squared:  0.9406, Adjusted R-squared:  0.9406 
## F-statistic: 1.585e+06 on 1 and 99998 DF,  p-value: &amp;lt; 2.2e-16&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Como esperado, a partir do modelo de regressão obtido acima a partir da população de parâmetros são conhecidos que o processo de geração da variável resposta ´y´ pode ser representado pela equação abaixo:&lt;/p&gt;
&lt;p&gt;&lt;span class=&#34;math inline&#34;&gt;\(y = 2x + 5 + \epsilon\)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;O histograma dos resíduos do modelo é mais uma evidência de que o modelo obtido possui boas propriedades:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;hist(resid(mod_populacao),
     main = &amp;quot;Distribuição dos resíduos do modelo da população&amp;quot;,
     xlab = NULL)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://www.sillasgonzaga.com/post/2018-07-01-a-equacao-mais-perigosa-do-mundo_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Assim, se tirarmos uma amostra da população e criarmos um modelo &lt;span class=&#34;math inline&#34;&gt;\(y = f(x)\)&lt;/span&gt;, os parâmetros do modelo dessa amostra serão os mesmos ou próximos ao da população, correto? Depende de seu tamanho.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;geracao-das-amostras&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Geração das amostras&lt;/h2&gt;
&lt;p&gt;A função abaixo cria 1000 amostras de tamanho &lt;strong&gt;&lt;code&gt;sample_size&lt;/code&gt;&lt;/strong&gt; do dataframe &lt;strong&gt;&lt;code&gt;df&lt;/code&gt;&lt;/strong&gt; dos dados da população e, para cada uma das amostras, ajusta um modelo de regressão linear, extrai o coeficiente de &lt;code&gt;x&lt;/code&gt; da regressão e retorna um dataframe com os resultados:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;coef_x_sample &amp;lt;- function(sample_size){
  repl &amp;lt;- purrr::rerun(1000, sample_n(df, sample_size))
  
  vec_coef_x &amp;lt;- repl %&amp;gt;% 
    map(~ lm(y ~ x, data = .)) %&amp;gt;% 
    map_dbl(~ coef(.)[&amp;quot;x&amp;quot;])
  
  data.frame(size = sample_size, coef_x = vec_coef_x)
}

# exemplo
set.seed(123)
head(coef_x_sample(10))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##   size   coef_x
## 1   10 2.065196
## 2   10 2.320681
## 3   10 2.142100
## 4   10 2.069578
## 5   10 2.036510
## 6   10 1.704862&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nas 6 primeiras amostras de tamanho 10, o coeficiente de x foi desde 1,70 a 2,32, mostrando uma certa variabilidade.&lt;/p&gt;
&lt;p&gt;O código abaixo repete o processo acima para valores diferentes do tamanho da amostra:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;vec_samp_size &amp;lt;- c(5, 10, 15, 20, 50, 75, 100, 150, 200, 250, 500, 750, 1000, 5000)

df_result &amp;lt;- vec_samp_size  %&amp;gt;% map_dfr(coef_x_sample)

df_result &amp;lt;- df_result %&amp;gt;% 
  mutate(size = factor(size, levels = vec_samp_size))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;analise-dos-resultados&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Análise dos resultados&lt;/h2&gt;
&lt;p&gt;Vários gráficos podem ser feitos para ilustrar os resultados da variabilidade do parâmetro da regressão em funcão do tamanho da amostra, como o boxplot abaixo:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df_result %&amp;gt;% 
  ggplot(aes(x = size, y = coef_x)) + 
  geom_boxplot() + 
  scale_y_continuous(breaks = seq(-4, 4, by = 1)) + 
  labs(x = NULL, y = NULL,
       title = &amp;quot;Variabilidade do coeficiente de x em função do tamanho da amostra&amp;quot;) + 
  theme_minimal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;http://www.sillasgonzaga.com/post/2018-07-01-a-equacao-mais-perigosa-do-mundo_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;O gráfico acima mostra que, apesar de a mediana ser aproximadamente 2 em todos os tamanhos amostrais testados, a variabilidade é muito maior nas menores amostras. A medida que se aumenta o número de indivíduos na amostra, a distribuição dos resultados converge para o valor verdadeiro. Para amostras de 5 indivíduos, foram observados resultados no seguinte intervalo:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# intervalo para menor tamanho amostral
range(df_result$coef_x[df_result$size == &amp;quot;5&amp;quot;])&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 0.3693973 3.6749739&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# intervalo para maior tamanho amostral
range(df_result$coef_x[df_result$size == &amp;quot;5000&amp;quot;])&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 1.973962 2.022880&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ou seja, mesmo que uma amostra seja oriunda de uma população descrita por parâmetros já determinados, usar resultados de uma amostra pequena pode levar a conclusões erradas.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>