Whatsapp vs produtividade

whatsapp2

Aproveitando o início de um novo ano, nada como pensar em coisas que gostaríamos de fazer: Um regime, começar academia, estudar X, mudar de emprego etc.

No meu caso, eu gostaria de diminuir o ‘ruído’.

Não tem muito tempo, me dei conta que estava com 4 softwares diferentes pingando conversas no meu computador, email, Skype for Business, Slack, whatsapp web enquanto que eu respondia um colega pelo Facebook Messenger no meu celular.

Vou dar um exemplo do que quero diminuir…

Whatsapp e seus grupos

Tenho um grupo no Whatsapp de mais ou menos uns 14 amigos que em média se conhecem há 15 anos e como foi dito internamente, é um ‘grupo sem propósito’, ele não tem uma função, objetivo ou finalidade mas foram trocadas 34.742 mensagens desde 20/10/2014.

dailyMessages

Vamos quebrar pelos 10 usuários mais ativos:

MessageCount

Para um grupo só até que é razoável, considerando que os usuários mandam me média 1.200 mensagens e recebem 2.200. (fonte)

Quando mandei esses gráficos no grupo, a primeira coisa que os ‘primeiros colocados’ responderam foi que estão acostumados a mandar várias mensagens em sequencia ao invés de um grande bloco de texto, por isso esses gráficos estavam inflados.

wordCount

MENTIRA!

Quebrei os textos por palavras e contei, o que aumentou ainda mais a distância dos ‘primeiros colocados’. Os três primeiros colocados correspondem a 48% do ruído gerado nesse grupo! (infelizmente eu sou era um deles)

Mas não é só isso, resolvi fazer uma análise do vocabulário olhando o número de palavras ‘únicas’ no texto de cada um e comparei com o número de mensagens. A tendência é clara, quanto mais se escreve, mais se repete. É o efeito “Vai Curintia!”, repetir isso a exaustão não te faz um cara mais legal…

Vocab_Palavras

Datas e horários

E quando é que essas mensagens aparecem?

WeeklyMsg

É lógico que é durante a semana…

hourlyMsgs

Bem no horário comercial, especialmente as 10:00…bem depois do primeiro café!

77,6% no horário ‘comercial’ (9:00 as 19:00)

82.9% de segunda a sexta

Se um usuário médio manda 1.200 mensagens e recebe 2.200 por mês, então ele sofre em média um pouco mais de 100 interrupções por dia no trabalho!!! Só no Whatsapp.

Tempo gasto

Só para termos uma noção de dimensão, vamos comparar a quantidade de texto produzida nesse grupo do Whatsapp com alguns livros:

WhatsVsLivros

Em um pouco mais de um ano, escrevemos coletivamente mais de 180.000 palavras,  3x o Livro Memórias Póstumas de Brás Cubas que tem 60.426.

Toma essa Machadão!

Multitasking

O maior problema disto é o efeito que realizar diversas tarefas tem no nosso cérebro, onde ao realizar diversas tarefas ao mesmo tempo, temos um desempenho inferior em todas.

http://www.forbes.com/sites/work-in-progress/2013/01/15/how-multitasking-hurts-your-brain-and-your-effectiveness-at-work/

http://www.forbes.com/sites/travisbradberry/2014/10/08/multitasking-damages-your-brain-and-career-new-studies-suggest/

Sem contar que isso atrapalha para entrar no estado de ‘flow’

https://en.wikipedia.org/wiki/Flow_%28psychology%29

O resultado é, 100 interrupções por dia do Whatsapp, um punhado do Slack, Skype, Facebook Messenger e trocentas notificações de recebimento de emails nas contas do trabalho e pessoal, além de Twitter e Facebook, é fácil afirmar que somos interrompidos pelo menos uma vez a cada dois minutos…

…Pelo menos o telefone raramente toca hoje em dia…

Próximos passos:

Eu gostaria de fazer uma análise no conteúdo dessas mensagens, porém alguns desafios se apresentam, como a informalidade, a coloquialidade da conversa, os erros e português e as figuras de linguagem. Por exemplo quando um chama o outro para jogar Age of Mythology…

“Zoomm!”

Outra coisa legal seria ver as relações entre o pessoal, mas para isso eu precisaria tratar os apelidos (e as vezes xingamentos) que se referem carinhosamente aos indivíduos do grupo.

Além disso, fazer uma análise de sentimento nos textos. Será que segundas feiras são mais tristes que sextas? É possível um texto negativo mudar o sentimento do grupo de negativo para positivo? Qual a intensidade necessária?

Por fim, que termos deixam o pessoal mais irritado?

Advertisements

Benchmarking CSV vs Parquet

Nos dias de hoje, provavelmente o formato mais utilizado para troca de dados é o CSV (Comma-separated values) e embora aqui no Brasil estejamos mais acostumados com a separação por ponto e vírgula me estranha muito um formato que existe desde a década de 70 perdurar até hoje.

Não dá para reclamar muito do bom e velho CSV, afinal é bem melhor do aquelas bases de dados do governo com separação fixa (por número de caracteres) ou as malditas planilhas de Excel.

Deve existir algo melhor, tem que existir algo melhor!

Em 2010 alguns caras do Google publicaram um artigo propondo uma nova forma de analisar dados chamada ‘Dremel’ onde segundo eles:

“Dremel is a scalable, interactive ad-hoc query system for analysis of read-only nested data. By combining multi-level execution trees and columnar data layout, it is capable of running aggregation queries over trillion-row tables in seconds. The system scales to thousands of CPUs and petabytes of data, and has thousands of users at Google. In this paper, we describe the architecture and implementation of Dremel, and explain how it complements MapReduce-based computing. We present a novel columnar storage representation for nested records and discuss experiments on few-thousand node instances of the system.”

Em outras palavras, Dremel é um sistema de consultas de bases gigantescas com seu formato em colunas e como sendo complementar a computação baseada em Map-reduce.

Bacana, mas eles não publicaram o código fonte, então os caras do Twitter juntamente com a Cloudera criaram em 2012 algo similar baseado no paper do Google chamado “Parquet” o qual em abril de 2015 se tonou um ‘Top Level Project’ na Apache foundation.

A ideia mesma, armazenar os dados em colunas de forma que nas consultas aos dados somente as colunas necessárias sejam escaneadas, isso trás basicamente alguns benefícios:

1 – Como somente as colunas necessárias são escaneadas as consultas tendem a ser muito mais rápidas

2 – É possível otimizar o fluxo de dados entre o processador e a memória (http://www.cidrdb.org/cidr2005/papers/P19.pdf)

3 – Os dados são mais facilmente comprimidos, pois os dados em forma de colunas são mais semelhantes entre si do que em linhas, imagine que você tem uma base de  7.000.000 de linhas, mas a coluna de UF tem 20 e poucos valores possíveis, sexo tem dois ou três valores, cor/raça tem meia dúzia e etc.

4 – Os dados em ‘Parquet’ já vem mapeados. Em um CSV nunca sabemos que tipo de valores estão contidos em uma coluna, se são texto, números, fatores, datas etc, no Parquet os dados já vem mapeados o que facilita demais! Isso me lembra a criação do MP3, que diferente do CD cada MP3 contém dados sobre o seu álbum como o artista, nome do álbum e até onde está a capa do álbum.

Não vou entrar muito em detalhes, caso contrário o post vai ficar muito longo, mas deixo a apresentação para quem tiver curiosidade.

 

E que vantagens isso trás?

Aproveitando meus posts anteriores onde já utilizo as bases de dados do Enem resolvi testar o formato para ver se realmente temos alguma vantagem sobre o csv.

O teste é simples, para diferentes tamanhos de amostra de dados do ENEM  (10.000 , 50.000, 100.000, … 300.000 linhas) faço a seguinte consulta:

Qual o percentual de alunos que não realizou a prova de Matemática por estado?

A mesma consulta é feita de 3 formas diferentes, ‘read.csv’ padrão do R, ‘read.df’ ainda lendo o CSV, mas usando uma instancia local do Spark e por fim via ‘parquetFile’ também no Spark. (o código está no final do post).

O resultado pode ser visto nos gráficos abaixo:

Rplot01

 

Até que funciona bem! Eu já sabia que o ‘read.csv’ do R era ineficiente, mas não tanto!

Rplot03

 

Comparando o ‘read.df’ e o Parquet ambos rodando no Spark, conforme aumentamos o tamanho do arquivo aumentamos a diferença de tempo entre eles, sendo que para um arquivo de 300.000 linhas ler um Parquet já é 15x mais rápido.

Rplot02

Por fim, como ‘bônus’ podemos ver que o tamanho de um arquivo CSV tende a ser um pouco mais de 8x maior do que o de um Parquet. Os dados do ENEM, por exemplo, vão de 5 e poucos GB para pouco mais de 700 megas.

 

Conclusão e próximos passos

Ao se tratar de ‘Big Data’ acredito que não temos o que discutir, vale a pena gastar um tempo convertendo as bases para Parquet para que estas sejam utilizadas depois com mais eficiência.

 

Já para ‘Small Data’, temos uma questão importante de como o R usa a memória, pois os arquivos são carregados na RAM e depois podem ser manipulados de maneira muito eficiente com o Dplyr. Já no Spark temos que alocar os arquivos na memória (comando ‘cache()’), na prática acaba dando no mesmo, porém pouca coisa é mais eficiente (e elegante) que o Dplyr.

Apesar dos ganhos serem significativos em termos percentuais não estou certo se vale a pena gastar tempo convertendo arquivos para um ganho de 30-40 segundos.

Algumas perguntas que precisam ser respondidas ainda:

  • Será que converter os arquivos ‘grandinhos’ para Parquet, carrega-los via Spark e usar ‘collect()’ para trazer para converter para Data.Frame do R e depois usar o Dplyr para manipula-los é uma opção?
  • Qual a diferença de tempo gasto em diversas operações no Spark-cache() vs R-Dplyr?
  • Usar o Spark com outro formato de dados é uma pentelhação, mas será que não vale a pena usar o mesmo processo para trabalhar com qualquer tipo de dados em qualquer lugar?

Código

rm(list=ls())
library(dplyr)
library(tidyr)
#library(ggplot2)

# Set this to where Spark is installed
Sys.setenv(SPARK_HOME="/home/sandor/spark-1.5.2-bin-hadoop2.6")
# This line loads SparkR from the installed directory
.libPaths(c(file.path(Sys.getenv("SPARK_HOME"), "R", "lib"), .libPaths()))
library(SparkR)


i <- 50
tCSV <- NULL
tPARQ <- NULL
size <- NULL
tNORM <- NULL
for (i in 1:25){
sc <- sparkR.init(sparkPackages = 'com.databricks:spark-csv_2.10:1.3.0')
sqlContext <- sparkRSQL.init(sc)
caminho <- '/home/sandor/Enem/2013/DADOS/MICRODADOS_ENEM_2013.csv'

####################
t1 <- Sys.time()
sample <- read.csv(caminho, sep = ';', nrows = i*12000)

sample %>%
dplyr::group_by(UF_PROVA,IN_PRESENCA_MT) %>%
summarise(N=n()) %>%
spread(IN_PRESENCA_MT, N) %>%
dplyr::mutate(Faltas=`0`/(`1`+`0`)*100) %>% dplyr::select(UF_PROVA, Faltas)

#nrow(sample)
tNORM[i] <- as.numeric(Sys.time()-t1)
####################

write.table(sample, '/home/sandor/Enem/2013/DADOS/MICRODADOS_ENEM_2013_SAMPLE.csv', sep=';', row.names = F)

####################
t1 <- Sys.time()
ENEM <- read.df(sqlContext, path='/home/sandor/Enem/2013/DADOS/MICRODADOS_ENEM_2013_SAMPLE.csv',
source = "com.databricks.spark.csv", inferSchema = "false", delimiter=';', header='true')
#count(ENEM)
registerTempTable(ENEM, "EE")
resCSV <- sql(sqlContext, "SELECT UF_PROVA, count(case IN_PRESENCA_MT when '0' then 1 else null end)/count(IN_PRESENCA_MT)*100 as Faltas
FROM EE
GROUP BY UF_PROVA")

collect(resCSV)
tCSV[i] <- as.numeric(Sys.time()-t1)
####################

unlink('/home/sandor/R_files/Parquet/base_1', force=T, recursive = T)
saveAsParquetFile(ENEM, '/home/sandor/R_files/Parquet/base_1')

####################
t1 <- Sys.time()
PARQ <- parquetFile(sqlContext,'/home/sandor/R_files/Parquet/base_1')
#count(PARQ)
#cache(PARQ)

registerTempTable(PARQ, "PQ")
resPQ <- sql(sqlContext, "SELECT UF_PROVA, count(case IN_PRESENCA_MT when '0' then 1 else null end)/count(IN_PRESENCA_MT)*100 as Faltas
FROM PQ
GROUP BY UF_PROVA")

collect(resPQ)
tPARQ[i] <- as.numeric(Sys.time()-t1)
####################

setwd('/home/sandor/R_files/Parquet/base_1')
sPARQ <- sum(file.info(list.files(".", all.files = TRUE, recursive = TRUE))$size)
sCSV <- file.size('/home/sandor/Enem/2013/DADOS/MICRODADOS_ENEM_2013_SAMPLE.csv')

size[i] <- sCSV/sPARQ
sparkR.stop()

}

Analisando o ENEM

Nos últimos posts tenho explorado maneiras de se trabalhar com Big Data no R. Apesar de nova, a integração do R com o Apache Spark é bem razoável e a implementação do Hive funciona bem, apesar de alguns percalços ao criar grupos, travamentos aleatórios e algumas configurações pentelhas.


Como utilizei os dados do Enem para montar o post anterior, ao olhar o dicionário de dados acabei pensando em algumas perguntas que poderiam ser respondidas com dados, entre elas:

– qual a relação entre renda e a nota?
– qual a relação entre os anos de estudo dos pais e a nota do aluno?

Essas duas são bem básicas e sua resposta é esperada…

Outras perguntas tem a ver com o sexo e cor/raça dos alunos ajustadas pela renda.

Por fim é possível descobrir quais questões os alunos mais erraram/acertaram.

1 – Renda

Renda

O primeiro gráfico era esperado, quanto maior a renda da família, maior a média da nota.

2 – anos de estudo do pai

Anos_Estudo

Mesma coisa do primeiro gráfico, quanto mais anos de estudo tem o pai, maior a média da nota.

Obviamente, quanto mais anos de estudo, maior a renda, ou será que é o contrário?*

* – essa discussão vai ficar para uma próxima oportunidade

3 – sexo

Participei do Big Data week no final de outubro e somente um palestrante era mulher, que por coincidência apresentou um gráfico mostrando que 12% dos programadores Java são mulheres.

Esse número é bem baixo, mas não é muita novidade para o pessoal de exatas e até mesmo para o pessoal da Economia.

Minha hipótese era de que essa decisão é tomada na adolescência, levado talvez por uma deficiência nos cursos de matemática.

O gráfico abaixo mostra a distribuição das notas de matemática entre homens e mulheres. De fato a mediana das notas das mulheres foi menor mas nada tão alarmante que fosse capaz de desencorajar uma pessoa de fazer um curso.

sexo
4 – cor/raça

Na minha época de cursinho no Anglo Tamandaré (próximo o bairro da liberdade em São Paulo) tinha uma frase escrita em todas as cabines do banheiro masculino:

– “Enquanto você está cagando tem um Japonês estudando”

Finalmente, depois de tantos anos, vou poder colocar esse dito popular a teste!

Ao agregar os números por cor e raça não conseguimos observar nada demais, porém, quando controlamos pela renda, assumindo que são estes os alunos competindo pelas melhores vagas (ver gráfico 01) a mediana da nota dos alunos que se classificam como “amarelos” é a maior de todas, nada muito significativo, mas maior de qualquer forma.

asia
Talvez aqui seja interessante fazer um teste de hipóteses para verificar se a nota é significativamente maior.

5 – perguntas mais difíceis.

Por fim, existe um campo na base com todas as respostas de cada aluno, bem como o gabarito, cruzei um com o outro para pegar os acertos e somei isso para pegar o número de acertos por questão, a questão com menor número de acertos foi a mais difícil.

Seguem as questões mais difíceis, eu apaguei a resposta, mas se você tiver curiosidade o nome da figura é a resposta:
MT_E CN_C CL_B CH_C

Microdados ENEM com R / Hadoop / Spark / Hive

A definição de Big Data que acho mais interessante é algo mais ou menos assim:

  • “Big Data são os dados que não cabem na memória RAM”

Quem desenvolve em R sabe que essa definição é perfeita…

O problema é que há uns 15 anos atrás HDs de 100GB de memória eram raros e de lá para cá essa capacidade de armazenamento aumentou muito. Atualmente HDs de 1TB são bem comuns, porém a velocidade com que os dados são lidos não aumentou na mesma velocidade. Então, para ler um HD inteiro, leva-se mais tempo hoje do que a 15 anos atrás.

Mapreduce

Até que alguém teve uma ideia muito simples que é ler dados de diversos HDs ao mesmo tempo, uma analogia interessante é:

Você tem que contar os livros de uma biblioteca, uma opção seria contar um a um até chegar no total ou chamar seus amigos e dizer:

  • “Ok, temos 8 corredores (MAP), cada um de vocês conta os livros de cada corredor(REDUCE) e me fala o total”

Atualmente a aplicação mais famosa de Mapreduce é o Hadoop, que é provavelmente o projeto de Open Source de maior impacto no mundo dos negócios até hoje.

O problema agora, como comentei no meu post anterior (https://dadosdadosdados.wordpress.com/2015/11/09/o-varian-pirou/ ), é que existe um gigantesco ecossistema de ‘coisas’ para estudar, aprender, usar e manter o que torna impraticável na ‘vida real’, ou vai demandar uma gigantesca dedicação.

Spark

SPARK

A partir de meados de 2015 o R foi integrado ao Spark, que é uma plataforma de computação em cluster que foi desenhada para ser rápida e genérica. Sua diferença básica com o Hadoop é que ele faz suas computações na memória (ram) ao invés de usar os discos (hd), isso permite a ele realizar cálculos que antes eram bem complicados de serem feitos em uma operação de Mapreduce comum.

Outro ponto importante é que ao invés de termos que focar em diversas tecnologias ao mesmo tempo, a filosofia do Spark é de prover um pacote completo para os analistas não terem que gastar tempo mantendo 15 sistemas ao mesmo tempo, o que diminui drasticamente os custos.

No final das contas, com o Spark conseguimos nos aproximar muito do modelo proposto pelo Varian para análise de dados, com um overhead menor, seja em custos de se manter sistemas, em horas de aprendizado.

Simulando um ambiente

Para efeitos de treino/testes, é possível simular um ambiente de Spark em apenas 01 cluster, ou seja, ao invés de distribuir os cálculos em várias máquinas, usamos somente nosso computador. Não é a coisa mais eficiente do mundo (computação distribuída em 01 computador não é distribuída), mas é possível desenvolver seu código nesse cluster único e depois subir para a nuvem quando ele estiver pronto.

Pré requisitos:

1 – Virtualbox
https://www.virtualbox.org/wiki/Downloads

Eu costumo configurar essas máquinas virtuais com 50GB de HD, 8GB de RAM e 64MB de memória de vídeo, essas configurações devem variar dependendo da máquina que você vai rodar isso.

No meu notebook eu uso 2GB de RAM e 12MB de vídeo somente.

2 – Linux no virtualbox – A versão que uso é o Mint (Rafaela)
http://linuxmint.com/

3 – Extension pack do Virtual box
https://www.virtualbox.org/wiki/Downloads

No linux:
4 – Java
$ sudo apt-get install openjdk-7-jdk
$ export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64

5 – Hadoop

https://hadoop.apache.org/docs/r2.5.2/hadoop-project-dist/hadoop-common/SingleCluster.html

6 – Hive
https://cwiki.apache.org/confluence/display/Hive/AdminManual+Installation#AdminManualInstallation-InstallingHive

7 – Spark – prestar atenção na versão do Hadoop, a versão pre-built serve
http://spark.apache.org/downloads.html

8 – R – Note que para o R, Trusty é a versão do Linux que estou usando, se você estiver usando uma versão diferente, é possível que você tenha que mudar o final do endereço

Adicionar em: /etc/apt/sources.list
deb https://cran.rstudio.com/bin/linux/ubuntu trusty/

Atualizar e instalar:
$ sudo apt-get update
$ sudo apt-get install r-base

$ R para checar a versão

9 – R-Studio
https://www.rstudio.com/products/rstudio/download/

Um caso real – Microdados ENEM

A pior coisa de usar tutoriais e demos é que tudo sempre dá certo, é uma beleza! O próprio tutorial do Spark usa um data.frame de umas 600 linhas, que meigo…

Eu encorajo a todos a tentarem algo diferente, para ver os problemas e dificuldades e o exemplo que vou mostrar aqui é dos microdados do ENEM.

É realmente uma pena a demora do INEP a divulgar os dados, pois os dados mais novos disponíveis são de 2013, mas é o que tem para hoje…

http://portal.inep.gov.br/basica-levantamentos-acessar

O legal dessa base de dados é que ela tem 5.1GB de dados, com 7.173.564 linhas e 166 colunas, o suficiente para travar minha máquina virtual, mesmo que ela possua 8GB de RAM, então ‘tecnicamente’ podemos considera-la como ‘BIG Data’.

Para essa análise quero comparar as notas das provas entre os estados do Brasil.

Rodando

O sparkR é realmente bacana, você basicamente precisa de dois comandos para começar a usar:

sc <- sparkR.init(master = 'local')
hiveContext <- sparkRHive.init(sc)

O primeiro comando inicia um contexto Spark e o segundo cria um contexto HIVE desse primeiro.

Depois, e é aí que as coisas começam a ficar diferentes de um exemplo comum, na hora de montar uma query no HIVE, você tem que declarar as colunas, o que é lindo quando você tem duas ou três, mas quando você tem 166 no caso do ENEM, você apela…

st <- rep('string', length(colnames(sample)))

st[match('NOTA_CN' ,colnames(sample))] <- 'int'
st[match('NOTA_CH' ,colnames(sample))] <- 'int'
st[match('NOTA_LC' ,colnames(sample))] <- 'int'
st[match('NOTA_MT' ,colnames(sample))] <- 'int'

Como queremos analisar somente as notas médias, vou forçar todos os campos a serem strings e somente a notas como números inteiros.

c1 <- paste(colnames(sample), st)
campos <- paste(c1, sep=',',  collapse = ', ')
cTable <- paste("Create external table src1 (", campos, ") row format delimited fields terminated by ';' SET skip.header.line.count = 1 ")

sql(sqlContext, "DROP TABLE src1")
sql(sqlContext, cTable)
sql(sqlContext, "LOAD DATA LOCAL INPATH '/home/sandor/Enem/2013/DADOS/MICRODADOS_ENEM_2013.csv' OVERWRITE INTO TABLE src1")

Agora é só agrupar os dados em um select comum

results1 <- sql(sqlContext, "SELECT UF_RESIDENCIA,
                avg(NOTA_MT) as AVG_MT,
                avg(NOTA_CN) as AVG_CN,
                avg(NOTA_CH) as AVG_CH,
                avg(NOTA_LC) as AVG_LC
                FROM src1 GROUP BY UF_RESIDENCIA")

Para transformar em data.frame do R usamos o comando ‘collect()’

tabela <- collect(results1)

Temos que pro fim ‘stopar’ o Spark

sparkR.stop()

O resultado

Agora, pegamos a nota média por estado por prova e subtraímos da média total para comparar as notas entre provas e estados.

Note que:

MT = Nota da prova de Matemática

LC = Nota da prova de Linguagens e Códigos

CH = Nota da prova de Ciências Humanas

CN = Nota da prova de Ciências da Natureza

plot of chunk unnamed-chunk-8

O Varian pirou?

Durante meus anos de estudo na universidade, Microeconomia tornou-se uma de minhas matérias preferidas e os livros texto do Varian certamente ajudaram a despertar esse interesse.

https://en.wikipedia.org/wiki/Hal_Varian

Em 2002 ele foi trabalhar no Google como um consultor e de lá para cá começou a se inclinar para o “Lado Negro da Força”.

Em 2009, Hal Varian comentou que o emprego mais ‘sexy’ dos próximos 10 anos seriam os estatísticos:

I keep saying the sexy job in the next ten years will be statisticians. People think I’m joking, but who would’ve guessed that computer engineers would’ve been the sexy job of the 1990s?”

E em 2013, publicou um artigo que capturou minha atenção, seu título é:

Big Data: New Tricks for Econometrics

http://people.ischool.berkeley.edu/~hal/Papers/2013/ml.pdf

E aí as coisas começaram a ficar mais interessantes…

O texto sobre Big Data e econometria tenta conciliar duas linhas de pensamento que até então andam separadas, que são a Econometria de um lado e os métodos computacionais de outro.

Para Varian, que está sentado em um trono de ouro no Google e possui centenas de engenheiros de software para fazer sua vontade, conectar Big Data e econometria ao mesmo tempo que propõe a utilização de novas ferramentas é trivial. Ele toca um sino e um estagiário traz um notebook em uma almofada vermelha para ele clicar ‘Run’.

A arrogância do texto é tanta que ele sugere logo nos primeiros parágrafos para que seus estudantes frequentem uma aula sobre “Machine Learning”:

…go to the computer science department and take a class in machine learning…

Resolvido…

 

O que ele sugere

No seu texto dedica basicamente 01 página as ferramentas para manipular big data (“01 Tools to manipulate big data“) e mostra em uma tabela as ferramentas que podem ser utilizadas. Resumidamente:

  • Hadoop File System: Um sistema de arquivos para ‘quebrar’ arquivos gigantescos em várias máquinas
  • Cassandra: Tabela de dados que vive no HDFS
  • Hadoop: Metodologia de ‘mapear’ os dados distribuídos em vários computadores e resumi-los fazendo calculos parciais (‘reduzidos’) em cada um deles
  • PIG: Uma linguagem específica para acessar esses dados
  • Hive, Drill, Impala: Funcionam de uma maneira semelhante ao PIG, mas são mais parecidas com os comandos SQL.

Fácil, não é? É só jogar meus arquivos nesse tal de HDFS e usar o PIG para fazer um resumo, o que pode dar errado?

A verdade é que não é tão fácil quanto parece. Existe um enorme buraco entre importar um arquivo de texto no Eviews versão estudante, Stata etc e utilizar as ferramentas sugeridas pelo Varian.

 

OK, então existem uma série de coisas para aprender, o que precisamos fazer?

Vou tentar fazer um breve resumo do que temos que aprender para poder começar a tentar trabalhar da forma proposta pelo Varian, eu estimo de 06 meses a 01 ano de estudo (dependendo da dedicação) para um estudante tornar-se proficiente em criar modelos que passem por todos os níveis da pilha, por isso o nível de sarcasmo dos próximos parágrafos é mais alto do que de costume neste blog.

Já ouviu falar do Linux? Essas coisas só funcionam bem nele, então a primeira coisa a fazer é montar um PC com o linux como sistema operacional.

Não tem um PC sobrando e não quer formatar sua máquina? Existem dois caminhos, ou você cria um dual boot para escolher qual o sistema operacional seu computador vai abrir ou cria uma máquina virtual usando, por exemplo o Virtualbox para rodar um linux dentro do windows. Essa última opção é mais lenta já que você fica com recursos compartilhados, mas é a melhor para quem está aprendendo.

Agora é só aprender a usar linux com linha de comando…

Depois, (felizmente) boa parte dessas tecnologias são open source o que é ótimo para aprender a usa-las, porém você vai eventualmente ter que instalar algumas coisas usando um negócio chamado Github, que de forma bem simplificada é um sistema usado para fazer controle de versões.

Então é só criar uma conta no github e aprender a usar por linha de comando, afinal você está no linux.

Obs: para o pessoal que está começando agora a escrever scripts no R, o github é de longe um dos melhores companheiros. Mesmo se você não trabalha em equipe, ter um controle das suas alterações e dos resultados intermediários da sua análise é algo fantástico.

Ótimo, agora temos um problema…as implementações do R ainda são limitadas e, principalmente para quem está aprendendo, não é uma boa seguir por modelos pre-estruturados como o Revolution Analytics ou Mapr, pois você fica amarrado. É possível até ser criativo, mas se vc quer a experiência completa, falta um pouco ainda para o R chegar lá.

Portanto você vai ser mais feliz usando o Python e veja só que legal, o linux geralmente vem com uma versão do Python instalada, então você não precisa instalar…

…Só aprender Python…( vale lembrar que hoje existem duas versões diferentes de Python rolando, então é bem comum você ter problemas com as versões)

Ótimo, agora é só instalar um Data serialization schema chamado AVRO, assim você pode mapear arquivos não estruturados.

Depois disso, instalar o PIG e aprender a usar…

Ótimo, agora estamos prontos para começar a brincar como o Varian…

 

Mais ou menos…

Com isso montamos a versão mais simples possível de uma pilha de tecnologia usando o Hadoop usando apenas 01 cluster (seu próprio PC), agora é possível começar a estudar como trabalhar com big data, mas para conseguir efetivamente tirar algum proveito você vai precisar escalar isso ou juntando vários PCs em um cluster ou usando algum serviço na nuvem como o Azure ou a Amazon, qualquer opção vai gerar custos altos para o estudante.

Em outras palavras, você se dedicou, estudou, estudou e estudou e no final das contas o resultado que você vai atingir usando sua aplicação caseira não é muito melhor do que abrir um CSV no R.

O verdadeiro ganho está em, quando surgir a necessidade, escalar essa aplicação na Nuvem e rodar o que for necessário de maneira escalável, portanto existe um bom valor em entender seu funcionamento. Essas aplicações na Nuvem costumam cobrar por horas de processamento, então você pode subir um cluster, processar o que precisa e desmontar, pagando alguns dólares por tudo.

 

Próximos passos

Essa é só a ponta do iceberg, tanto que o que descrevi acima é chamado de Hadoop 1.0, implementações mais modernas usam o Hadoop 2.0 que tem diversas melhorias na redundância dos dados, na forma como os clusters são gerenciados e trocentas formas diferentes de trabalhar os dados no HDFS.

hadoopstack

Na minha opinião, o Varian não pirou ( talvez só um pouco) , pois as tecnologias por ele sugeridas seriam reproduzíveis por um estudante em casa, o problema é a quantidade de trabalho e estudo que isso demanda.

Em um futuro próximo vejo que a melhor forma de conciliar a Econometria com Big Data seria o trabalho colaborativo entre pessoas com diferentes habilidades ou a utilização de pilhas de tecnologia pre-configuradas como o Cloudera, Revolution Analytics, Mapr, Horton, HDinsight e etc, mas ainda assim não nos livramos de ter que aprender uma série de novas tecnologias para fazer basicamente a mesma coisa que antigamente, só que maior…

Trabalhando com séries temporais no R – Parte II (estatísticas fiscais)

No post anterior (link) demonstrei como importar e definir séries temporais no R quando o vetor de datas não está no formato adequado (no caso de estar formatado como texto, por exemplo). Esse é um problema bastante comum e precisa ser tratado independente do software que o analista está utilizando.

Também destaquei que os canais de acesso à informação (IBGE, Banco Central, Ipeadata, etc.) não seguem um padrão de armazenamento dos dados – geralmente disponibilizam as séries no formato que julgam ser mais conveniente. Mas em alguns casos a formatação dos dados não está relacionada à preferência de quem os divulga. Algumas bases têm de seguir certas normas e padrões internacionais. Esse é o caso das séries de finanças públicas do Banco Central do Brasil.

Devido ao grande número de indicadores, as estatísticas fiscais seguem um padrão de divulgação bastante diferente daquela estrutura que trabalhamos no nosso primeiro exemplo; os dados estão dispostos nas colunas e os rótulos nas linhas. Além disso, na maior parte dos casos não há sequer um vetor de datas e qualquer preocupação de atribuir códigos exclusivos para cada uma das séries, de modo a facilitar a vida do analista quando, em uma mesma base, existem séries com nomes (rótulos) idênticos.

Neste exemplo utilizaremos as séries históricas de Necessidade de Financiamento do Setor Público, disponível na seção de séries temporais do site do Bacen (link). Este conjunto de dados foi escolhido por dois motivos. Primeiro porque atende os três pré-requisitos de base pentelha: (i) dados transpostos, (ii) sem vetor de datas e (iii) ausência de códigos exclusivos em cada indicador. Em segundo lugar, porque este é o assunto do momento – o mundo todo está atento para a forte e rápida deterioração da situação fiscal brasileira, principalmente por conta da incapacidade do governo de cortar gastos, mas também pela queda abrupta da arrecadação federal (afetada sobremaneira pela desaceleração da atividade econômica).

Nosso objetivo é exatamente o mesmo do alcançado no post anterior: deixar a série de dados no formato mais adequado, para posteriormente podermos utilizar todo instrumental de data analysis do R. Também lançaremos mão de um recurso incrível do R: baixar os dados diretamente da fonte e extrair o “zip” para uma pasta temporária do computador. Isso será especialmente útil para aqueles que precisam atualizar mensalmente bases, apresentações gráficas ou modelos econométricos.

O código foi escrito em oito passos. Para não poluirmos os comandos com diversos comentários, descreverei abaixo o que está sendo feito em cada etapa.

  • 1o passo: cria pasta temporária; baixa o arquivo “zip” do site do Bacen e salva na pasta criada; extrai os arquivos para a pasta; cria base “original” com os dados da aba “$-12meses(corrente)”.
  • 2o passo: deleta as linhas e colunas da base “original” onde todas as células estão como “NA”; cria “base1” deixando apenas as linhas com as informações que interessam.
  • 3o passo: cria um vetor de datas baseado no número de colunas (exclusive a coluna A de nomes), definindo apenas a data de início da série; renomeia os rótulos das colunas da “base1” com o vetor de datas, e as linhas com o número de linhas.
  • 4o passo: cria um vetor simples de referência (REF) que “codifica” as linhas para facilitar a escolha dos indicadores; adiciona esse vetor na primeira coluna da “base1”.
  • 5o passo: cria a “base2” convertendo a “base1” para o formato long (mais adequado).
  • 6o passo: converte cada coluna da “base2” para o formato adequado. No vetor de nomes (coluna “Indicador”), remove espaçamento extra (“ Nominal” vira “Nominal”). O vetor de datas é convertido para “aaaa/mm/dd”, o padrão internacional. Já o vetor de Valor é convertido para o formato numérico.
  • 7o passo: cria a “base3”, a partir da “base2”, selecionando o indicador de interesse (REF: 21 = “Primário”), que representa o resultado primário do setor público consolidado no acumulado em 12 meses; divide a coluna de valor por 1.000 (para representar em R$ Bilhões) e inverte o sinal.
library(XLConnect)
library(lubridate)
library(ggplot2)
library(dplyr)
library(reshape2)
library(xlsx)
library(scales)

# 1o PASSO
temp <- tempfile()
download.file("http://www.bcb.gov.br/ftp/notaecon/nfspp.zip", temp)
unzip(temp)
original <- read.xlsx(temp, file = "Nfspp.xls", 
                       sheetName = "$-12meses(corrente)", as.data.frame = TRUE,  
                       encoding = "UTF-8")

unlink(temp)

# 2o PASSO
original <- original[rowSums(is.na(original)) != ncol(original),]
original <- original[,colSums(is.na(original)) != nrow(original)]
base1 <- original[rowSums(is.na(original)) == 0,]

# 3o PASSO
meses <- ncol(base1)-1
datas <- seq.Date(as.Date("2002-11-01"), by = "month", length.out = meses)
colnames(base1) <- c("Indicador", as.character.POSIXt(datas))
row.names(base1) <- 1:nrow(base1)

# 4o PASSO
REF <- row.names(base1)
base1 <- cbind(REF, base1)

# 5o PASSO
base2 <- melt(base1, id = c("REF", "Indicador"), variable.name = "Data", value.name = "Valor")

# 6o PASSO
base2$Indicador <- gsub("\\s+"," ", base2$Indicador) 
base2$Data <- as.POSIXct(parse_date_time(base2$Data, "%Y/%m/%d"))
base2$Valor <- as.numeric(base2$Valor)

# 7o PASSO
selecao <- "21"
base3 <- filter(base2, REF == selecao)
base3$Valor <- base3$Valor/1000*(-1)

8o passo: cria gráfico de linha a partir da “base3”; as opções colocam título, linha reta cruzando o eixo Y no ponto zero, modificam a escala do eixo X para meses e colocam títulos nos eixos.

Pelo gráfico abaixo é possível perceber a forte deterioração do resultado primário do setor público consolidado (que considera o governo federal, os estados e municípios, bem como as empresas estatais não financeiras, exceto a Petrobras e o grupo Eletrobras) desde o final do primeiro trimestre de 2014. É mais do que justificável, portanto, a desconfiança do mercado na capacidade do governo de produzir um superávit primário de R$ 8,747 bilhões (0,15% do PIB) em 2015, uma vez que o resultado acumulado até agosto está negativo em R$ 43,8 bilhões.

# 8o PASSO
graf1 <- ggplot(base3, aes(Data, Valor)) + 
  geom_line(colour = "red", size = .7) + 
  ggtitle("Resultado Primário do Setor Público \n Acum. 12 meses. Elaboração: dadosdadosdados") + 
  theme(plot.title = element_text(lineheight=.9, face="bold")) + 
  geom_hline(yintercept=0, col = "black", linetype = "dashed") +
  scale_x_datetime(breaks = date_breaks("8 months"), labels = date_format("%b/%y")) +
  theme(axis.text.x = element_text(angle = 90))
update_labels(graf1, list(y = "R$ Bilhões", x = ""))

plot of chunk unnamed-chunk-3

Por fim, selecionaremos mais de 1 indicador para colocar no gráfico, e também reduziremos a amostra de análise. Assim poderemos observar composição mais recente do resultado primário por esfera de governo (nível federal e regional).

O resultado final é o destacado no gráfico abaixo.

# Selecionando mais indicadores e reduzindo a amostra  
selecao <- c("22", "27", "30", "31")
base3 <- filter(base2, REF %in% selecao)
base3$Valor <- as.numeric(base3$Valor)
base3$Valor <- base3$Valor/1000*(-1)

amostra <- filter(base3, Data >= "2012-12-01" & Data <= "2015-08-01")
## Warning in data.matrix(data): NAs introduced by coercion
  graf2 <- ggplot(amostra, aes(x=Data, y=Valor, fill=Indicador)) + 
    geom_bar(stat="identity") + 
    ggtitle("Resultado Primário do Setor Público \n Acum. 12 meses. Elaboração: dadosdadosdados") + 
    theme(plot.title = element_text(lineheight=.9, face="bold")) + 
    geom_hline(yintercept=0, col = "black", linetype = "dashed") +
    scale_x_datetime(breaks = date_breaks("2 months"), labels = date_format("%b/%y")) +
    theme(axis.text.x = element_text(angle = 90), legend.position = "bottom") 
  update_labels(graf2, list(y = "R$ Bilhões", x = ""))
## Warning: Stacking not well defined when ymin != 0

plot of chunk unnamed-chunk-4

Trabalhando com séries temporais no R – Parte I

O principal objeto para armazenamento de dados no software R é o data.frame, que representa uma estrutura retangular onde cada coluna pode abrigar informações de diferentes tipos (números, textos, datas, etc.). Embora o R seja uma ferramenta poderosa para se trabalhar com qualquer tipo de dado, no seu estado natural (ou seja, sem a ajuda das bibliotecas criadas pela comunidade de usuários), manejar séries de tempo pode ser frustrante, sobretudo se os dados não seguirem um padrão fixo de espaçamento – como ocorre, por exemplo, com séries intraday do mercado financeiro.

O pacote básico do R inclui duas classes para operações com séries de tempo: a ts para dados univariados e a mts para dados multivariados, que são úteis para trabalhar com dados mensais e trimestrais (de espaçamento fixo), mas que contam com poucas funções (métodos) de manipulação e processamento dos dados, além de uma interface gráfica bem pobre.

A partir dessas limitações, diversos pacotes foram criados para tornar mais fácil a vida dos que querem brincar com séries temporais no R. Os mais conhecidos são o zoo e o xts, que basicamente armazenam os dados em dois componentes: (i) um vetor de datas e/ou tempo e (ii) um data.frame com as observações (dados). Os pacotes de séries de tempo servem para combinar estes dois elementos e possibilitar a aplicação de diversas funções.

Mas antes de começarmos a trabalhar com as séries de tempo, serão necessárias mais algumas bibliotecas (nesse caso, o XLConnect e o lubridate), visto que precisaremos importar os dados de interesse para o R e muito provavelmente padronizar o vetor de datas. Aliás, em um típico processo de análise, a qualquer momento as etapas podem incluir alguma transformação dos dados, imputação de valores inexistentes, adicionar/deletar variáveis e recomeçar o processo inteiro novamente (como mostrado na figura abaixo).

fig 1

Nesse momento você deve estar se perguntando: por que diabos preciso me preocupar em padronizar o vetor de datas? A resposta passa pelo fato de que, no Brasil, cada fonte divulga seus dados da forma como acha conveniente e, na maioria das vezes, este formato não é o mais apropriado. Um exemplo clássico é o Ipeadata (link) – repositório gratuito de dados macroeconômicos, regionais e sociais de diversas fontes domésticas e internacionais -, que divulga o vetor de datas como texto (COMO TEXTO!). Em séries mensais o formato utilizado pelo Ipea é o “YYYY.MM”. Ou seja, a referência para set/15, que deveria ser 01/09/2015, é armazenada na coluna A como “2015.09”. Aí dificulta a vida do cidadão! Mas não se preocupe… com uma linha de comando o R resolve isso.

Neste post mostrarei como importar uma base para o R, transformar dados em séries temporais e também os primeiros passos de como gerar gráficos mais elegantes e elaborados. Nas próximas publicações partiremos para análises de decomposição, construção/avaliação de modelos de previsão e projeções de valores futuros.

No nosso exemplo, utilizaremos os dados do IBC-Br (indicador proxy do PIB, criado pelo Banco Central do Brasil), baixados lá no site Ipeadata. Basta acessar o link e digitar no campo de pesquisa o termo “IBC-Br” (sem as aspas). A série que nos interessa é a “Índice de Atividade Econômica do Banco Central (IBC-Br) (2002=100)”. Agora é só exportar em formato “xls”. De preferência, nomeie a planilha como “IBCBR.xls”, pois é este o nome que utilizaremos no código.

A tabela abaixo resume as funções e pacotes que utilizaremos no código.

fig 2

library(zoo)
library(XLConnect)
library(lubridate)
library(ggplot2)

#Importando os dados e renomeando as colunas
setwd("C:\\Users\\Tho\\Google Drive\\Blog\\201509\\")
wb <- loadWorkbook("IBCBR.xls")
  Matriz <- readWorksheet(wb, sheet = "Séries", startRow = 0, startCol = 0)

#alterando o vetor de datas para o formato correto   
  names(Matriz) <- c("Data", "IBCBr")

  Matriz$Data <- parse_date_time(Matriz$Data, "%Y.%m")

#transformando dados em time-series     
  tsIBCBr <- zoo(Matriz$IBCBr, Matriz$Data)

O resultado final é o destacado no gráfico abaixo.

#gerando gráficos mais elaborados      
  lc <- qplot(Data, IBCBr, data = Matriz, geom = "line") + 
    geom_line(colour = "red", size = .7)
  lc + ggtitle("IBC-Br (2002=100, Banco Central do Brasil) \n Elaboração: dadosdadosdados") + 
    theme(plot.title = element_text(lineheight=.9, face="bold"))

plot of chunk unnamed-chunk-3