Skip to main content
13 fevereiro 2020
Follow Us

Power BI and R: living together

Participei recentemente num evento organizado pela Porto.Data como orador para mostrar como é possível integrar alguns modelos preditivos desenvolvidos com a linguagem R no Power BI. O feedback que recebi dos participantes no final foi muito entusiástico e creio que todos se aperceberam do grande potencial na combinação de uma ferramenta amigável de visualização de dados, como o Power BI, e uma poderosa ferramenta de análise de dados avançada, como a R (ainda que esta seja menos amigável).

Aqui ficam as principais conclusões deste meetup. Mais uma vez, obrigado a todos pelo feedback.

Power BI e R: uma combinação explosiva

O Power BI já deve dispensar apresentações. Em 2020 é líder mundial em tecnologias de Business Intelligence. É uma ferramenta gratuita, amigável e fácil de utilizar da Microsoft, que recolhe dados provenientes de diversas fontes e os transforma em visualizações interativas e que funcionam num computador, browser ou dispositivos móveis.

A adoção do Power BI em todo o tipo de organizações, sejam empresas ou sem fins lucrativos, tem sido explosiva. Por um lado, porque existe um benefício óbvio na automação de processos de reporting, e, por outro, porque é possível manter os dados sempre atualizados.

Em relação à linguagem R, também existem muitas vantagens na sua adoção. Destaco as que me parecem mais interessantes:

  • É uma linguagem “open-source”, com uma enorme comunidade de contribuidores, o que significa que é gratuita e está em constante evolução.
  • Dispõe de algoritmos de machine learning muito interessantes para desenvolver praticamente todo o tipo de modelos analíticos descritivos e preditivos.
  • É muito versátil em termos de construção de visualizações, permitindo o desenvolvimento personalizado de gráficos e diversos elementos visuais.
  • Permite o desenvolvimento de apps que funcionam num browser.
  • E finalmente, corre no Power BI!

Portanto, juntando estas duas peças, é possível:

  • Construir modelos de análise preditiva,
  • Realizar diversas operações de transformação de dados mais rapidamente e / ou que seriam impossíveis de realizar de outro modo,
  • Desenvolver visualizações em R e utilizá-las no Power BI.

Como colocar em prática a integração da linguagem R com o Power BI?

Em primeiro lugar, são necessários dados. Na minha apresentação utilizei dados reais fornecidos pela Olist, uma empresa brasileira de e-commerce. Esta empresa funciona como um market place – de um lado, vendedores de diversos tipos de produtos de grande consumo e de outro, consumidores finais.

Aqui está um resumo do modelo de dados, no Power BI Desktop:

POWER BI R1

Começamos a explorar estes dados usando algumas visualizações do Power BI. Nestas, é possível observar o crescimento expressivo ao longo do tempo desta plataforma nos anos 2017 e 2018 a vários níveis: número de utilizadores, número de produtos e valor transacionado.

Esta empresa regista precisamente outras variáveis interessantes, como os tempos de entrega e de atraso (face à data prevista de entrega), assim como o nível de satisfação do cliente, medido através de inquéritos de satisfação.

Como podemos ver na imagem seguinte, os clientes estão distribuídos por todo o Brasil e a maioria das transações refere-se a produtos de grande consumo, como artigos de beleza, relógios, etc.

POWER BI R2

Ativar o R e o R Studio

Antes de podermos utilizar a linguagem R no Power BI Desktop, é necessário instalá-la no nosso computador. Para tal, podemos simplesmente fazer download da mesma a partir do link: https://cran.r-project.org/

POWER BI R3

Vale a pena navegar neste site e explorar o seu conteúdo (e no design que recorda os tempos em que ligávamos o modem à tomada do telefone para aceder à Internet) e descobrir a documentação do R, manuais e packages que ampliam a sua capacidade base.

Como o editor da linguagem R fornecido com a instalação é muito básico, vamos usar o R Studio, um mais avançado e amigável. Também é gratuito e pode ser descarregado a partir do link: https://rstudio.com/

Se tudo correr bem, instalámos o R e o R Studio e agora teremos de os ativar no Power BI Desktop, a partir das opções de configuração:

POWER BI R4

Visualizações R no Power BI

Com este ambiente, podemos acrescentar visualizações do R ao Power BI. O processo consiste em selecionar essa visualização no painel e acrescentar os campos com os dados à área de valores:

POWER BI R5

No próprio Power BI Desktop é possível abrir um editor incorporado onde introduzimos o código R. No entanto, esta prática não é a mais adequada, na minha opinião. Primeiro, porque o editor está a correr o R e o R Studio nos bastidores que, se usados diretamente funcionam de forma mais rápida. Por outro lado, em caso de erro, é mais fácil fazer o “debugging” diretamente no R Studio do que no Power BI Desktop.

Por isso, sugiro que corram todo o código no R Studio e só depois de validado o código, o copiem e colem no Power BI:

POWER BI R6

Para fazer alguns gráficos interessantes, vamos precisar de correr o seguinte código, que pode ser dividido em três partes:

  1. Carregamento de alguns packages
  2. Transformação de dados
  3. Criação de gráficos
################## Carregamento de packages
library(tidyverse)
library(lubridate)
library(ggthemes)
library(gridExtra)
library(tidytext)
library(tidyr)

################## Importação de dados
setwd("C:/Meetup/dados")
dataset <- read_csv("olist_public_dataset_v2.csv")

str(dataset)
summary(dataset)

################# Transformaçao de dados
# selecionar apenas as encomendas válidas
# acrescentar algumas colunas novas
dataset_aprov <- dataset %>%
filter(order_status == 'approved' |
order_status == 'delivered' |
order_status == 'invoiced' |
order_status == 'shipped') %>%
mutate(data_compra = date(order_purchase_timestamp),
data_hora_compra = ymd_hms(order_purchase_timestamp),
hora_compra = hour(order_purchase_timestamp),
dia_semana = wday(order_purchase_timestamp),
nome_dia_semana = factor(weekdays(order_purchase_timestamp),
levels =c("domingo","segunda-feira", "terça-feira", "quarta-feira", "quinta-feira", "sexta-feira", "sábado")),
ano_compra = factor(year(data_compra)))

str(dataset_aprov)

# resumo por ano
resumo_por_ano <- dataset_aprov %>%
group_by(ano_compra) %>%
summarise(valor_produto = sum(order_products_value),
valor_frete = sum(order_freight_value),
num_produtos = sum(order_items_qty))

# resumo por dia da semana e hora
resumo_por_dia <- dataset_aprov %>%
group_by(hora_compra,
nome_dia_semana) %>%
summarise(numero_encomendas = n())

################## Criação de gráficos
# gráficos colunas
ggplot(resumo_por_ano, aes(x = ano_compra, y = valor_produto))+
geom_col()+
ggtitle("Valor do produto por ano")+
xlab("Ano")+
ylab("Valor produto")+
theme_economist()

# boxlots
ggplot(dataset_aprov, aes(x= ano_compra, y = order_items_qty))+
geom_boxplot()+
ggtitle("Valor do produto por ano")+
xlab("Ano")+
ylab("Valor produto")+
theme_economist()

ggplot(dataset_aprov, aes(x= ano_compra, y = order_products_value))+
geom_boxplot()+
ggtitle("Valor do produto por ano")+
xlab("Ano")+
ylab("Valor produto")+
scale_y_log10()+
theme_clean()

ggplot(dataset_aprov, aes(x= ano_compra, y = order_freight_value))+
geom_boxplot()+
ggtitle("Valor do frete por ano")+
xlab("Ano")+
ylab("Valor produto")+
scale_y_log10()+
theme_economist()

# histogramas
ggplot(dataset_aprov, aes(x = order_items_qty))+
geom_histogram(binwidth = 1)+
ggtitle("Número de produtos por encomenda")+
xlab("Quantidade de produtos")+
ylab("Contagem")

plot1 <- ggplot(dataset_aprov, aes(x = order_products_value))+
geom_histogram(color ="white", position = "identity")+
ggtitle("Valor de produto por encomenda")+
xlab("Valor de produto")+
ylab("Contagem")+
theme_economist()

plot2 <- ggplot(dataset_aprov, aes(x = log10(order_products_value)))+
geom_histogram(color ="white", position = "identity")+
ggtitle("Valor de produto por encomenda (log)")+
xlab("Valor de produto (log)")+
ylab("Contagem")+
theme_economist()

grid.arrange(plot1, plot2, ncol=2)

ggplot(dataset_aprov %>% filter(ano_compra !=2016),
aes(x = log10(order_products_value),
color = ano_compra))+
geom_histogram( position = "identity")+
ggtitle("Valor de produto por encomenda (log)")+
xlab("Valor de produto (log)")+
ylab("Contagem")+
scale_color_manual(values=c("#999999", "#E69F00", "#56B4E9"))+
scale_fill_manual(values=c("#999999", "#E69F00", "#56B4E9"))+
theme_economist()+
theme(legend.position="right")+
labs(color ="Ano")

# Heatmap
ggplot(resumo_por_dia, aes(hora_compra, nome_dia_semana))+
geom_tile(aes(fill = numero_encomendas), colour = "white") +
scale_fill_gradient(low = "white", high = "steelblue")+
ylab("Dia da semana")+
xlab("Hora de compra")+
ggtitle("Heatmap número de encomendas por dia da semana e hora")+
labs(fill ="Nº enc.") +
scale_x_discrete()+
theme(legend.position="right")+
theme_clean()

Como resultado deste código, no Power BI obtemos uma nova página com as seguintes visualizações:

POWER BI R7

O primeiro é um simples gráfico de colunas, que também poderia ser obtido com o gráfico do Power BI. No entanto, os restantes gráficos são personalizados no R e não se obteriam no Power BI:

  • O heatmap resume o número de encomendas por dia da semana e hora de compra
  • Os boxplots mostram-nos dados estatísticos sobre o valor transacionado por ano, incluindo quartis, mediana e outliers
  • Por fim, os histogramas com o valor transacionado por encomenda podem ser apresentados em conjunto num só e um deles adotar uma escala logarítmica para facilitar a análise.

Modelo de clustering no Power BI

Na primeira página deste relatório vimos que a empresa teve mais de 50 mil clientes em 2018. Mas como se caracterizam? Para responder a esta questão, podemos recorrer de um algoritmo de clustering.

O clustering é um modelo que agrupa objetos (neste caso, clientes) de acordo com características comuns. É relativamente fácil agrupar os clientes de acordo com a sua localização geográfica, idade, género ou outra dimensão de que disponhamos no modelo de dados. Mas é bastante mais complexo fazer esse agrupamento com base em comportamentos de compra, como por exemplo, quantos produtos comprou, qual a pontuação média que atribuiu, se costuma ou não deixar comentários quando realiza uma compra, etc.

No código abaixo demonstro como resolver este problema com o package “cluster” do R:

############################################################
# Clustering de clientes
############################################################

# importar tabela clientes
customers <- read_csv("/olist_customers_dataset.csv")

# acrescentar unique id do cliente
customers_id <- customers %>%
select(customer_id, customer_unique_id)

# join com a tabela transacional e customer unique id
dataset_customer<- inner_join(customers_id, dataset_aprov, by = "customer_id")

dataset_customer <- dataset_customer %>%
mutate(
atraso_entrega_mins = difftime(order_delivered_customer_date, order_estimated_delivery_date,
units = "mins"),
tempo_entrega_mins = difftime(order_delivered_customer_date, order_aproved_at,
units = "mins")) %>%
distinct(customer_unique_id, .keep_all = T)

# resumo por cliente
resumo_por_cliente <- dataset_customer %>%
filter(order_status == 'delivered') %>%
group_by(customer_unique_id) %>%
summarise(
valor_produto = sum(order_products_value),
num_produtos = sum(order_items_qty),
pontuacao_media = mean(review_score)) %>%
inner_join(select(dataset_customer, atraso_entrega_mins, tempo_entrega_mins, customer_unique_id),
resumo_por_cliente, by = "customer_unique_id")

resumo_por_cliente$atraso_entrega_mins<- as.numeric(resumo_por_cliente$atraso_entrega_mins)
resumo_por_cliente$tempo_entrega_mins<- as.numeric(resumo_por_cliente$tempo_entrega_mins)

# Eliminar NA's
library(DMwR)
resumo_por_cliente <- na.omit(resumo_por_cliente)

# Normalizar features
resumo_por_cliente_z <- as_tibble(scale(resumo_por_cliente[,-1]))
summary(resumo_por_cliente_z)

# avaliar quantos clusters são necessários
# retirar amostra aleatória de 25%
# demorado - devolveu 4 clusters
resumo_por_cliente_z_sample <- sample_frac(resumo_por_cliente_z, 0.25)
# fviz_nbclust(resumo_por_cliente_z_sample, kmeans, method = "wss")

############# Power BI ##############
# criar clusters
library(cluster)
clusters <- clara(resumo_por_cliente_z, 4, samples = 50, pamLike = T)
clusters$medoids

# acrescentar dimensão cluster
resumo_por_cliente$cluster <- as.factor(clusters$clustering)
clusters$clusinfo # dimensão, dissimilaridade e isolamento

O resultado deste código é que agora cada um dos clientes desta empresa tem um cluster associado. O algoritmo identificou 4 clusters como o número ideal de clusters, mas funcionaria com qualquer outro número pelo que seria ótimo se nesta fase obtivéssemos o input por parte dos gestores desta empresa.

Usando a interatividade das visualizações do Power BI é muito fácil caracterizar estes clusters. Veja-se por exemplo como se diferenciam a nível da pontuação média e como esta parece estar relacionada com os tempos e atrasos na entrega. Será que o número de produtos e respetivo valor estão relacionados? E como se relacionam todas estas variáveis com os Estados e as categorias de produto que compram?

Esta análise enriqueceu substancialmente o modelo de dados e fornece uma ferramenta de marketing:

POWER BI R8

Em futuros artigos, mostrarei como continuou o resto da apresentação onde expliquei como fazer um modelo preditivo com R e Power BI para a pontuação dos clientes e como analisar o texto com os comentários.

Obrigado!


Assine a nossa newsletter e receba o nosso conteúdo diretamente no seu email