Introdução
Este tutorial irá mostrar como instalar o R e o PostgreSQL num mesmo servidor Ubuntu 18.04 ou 16.04. Em seguida, falaremos sobre como chamar o R a partir do Postgres.
Farei uma série de tutoriais. Este primeiro é voltado para aqueles com familiaridade com funções do R e que gostariam de rodá-las no PostgreSQL, sem necessariamente conhecer muito SQL.
Num próximo, iremos mostrar como criar queries e declarações do PostgreSQL do R, ou seja, será mais voltado para quem tem familiaridade com o SQL, mas não necessariamente versada em R.
Os tutoriais posteriores serão voltados para aqueles com bastante familiaridade em tidyverse e que gostariam de realizar as mesmas coisas em SQL. Igualmente, servirão para aqueles que sabem manipular dados em SQL, mas gostariam de fazer as mesmas coisas no R.
Em futuros tutoriais, falaremos quando compensa iniciar no PostgreSQL e terminar no R. Por exemplo, quando é mais vantajoso dar um join no R em vez de fazê-lo no PostgreSQL e vice-versa.
Instalando o PostgreSQL
A primeira coisa a fazer é atualizar os pacotes do sistema:
sudo apt update
sudo apt -y install vim bash-completion wget
sudo apt -y upgrade
Feito isso, dê um reboot:
sudo reboot
Importe a chave GPG:
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
Adicione a chave GPG ao systema:
echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" |sudo tee /etc/apt/sources.list.d/pgdg.list
Atualize os pacotes do sistema e instale os pacotes do PostgreSQL necessários. Os dois primeiros são necessários para rodar o PostgreSQL, os três últimos são necessários para instalar o plr
, o RPostgres e outras extensões. Falaremos deles mais adiante.
sudo apt update
sudo apt install postgresql-12 postgresql-client-12 postgresql-server-dev-all libpq-dev postgresql-contrib
Instalação do R
sudo echo "deb https://cloud.r-project.org/bin/linux/ubuntu `lsb_release -cs`-cran40/" | sudo tee -a /etc/apt/sources.list
Adicionar a chave GPG
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9
Instale o R
sudo apt-get update
sudo apt-get install -y r-base r-base-dev
Instale também o git
sudo apt install git
Agora use o git para clonar o plr. Não importa o local onde você irá cloná-lo. Desde que você tenha seguido fielmente os passos anteriores, tudo terminará bem.
git clone https://github.com/postgres-plr/plr
Feito isso, entre no diretório plr e rode os seguintes comandos para instalá-lo como extensão.
cd plr
USE_PGXS=1 make
USE_PGXS=1 make install
Criando uma base de dados
Vamos para o Postgres a fim de criar uma base de dados.
sudo -u postgres psql
CREATE DATABASE datasets;
Além disso, você deve incluir a extensão plr
na base de dados recentemente criada:
\c datasets -- conectar-se à base
CREATE EXTENSION plr;
\q -- sair do psql
De volta ao R.
R
Instale os pacotes RPostgres
e broom
Instalando esses dois pacotes é suficiente para instalar também outras dependências como o DBI e o dplyr, as quais igualmente usaremos.
install.packages(c("RPostgres","broom"))
Connexão do R ao Postgres
Eventualmente, você terá de autorizar a conexão local. Vá para o arquivo:
vim /etc/postgresql/12/main/pg_hba.conf
E altere a seguinte linha de:
local all all peer
Para:
local all all trust
Colocando uma tabela na base de dados
Admitindo que você ainda se encontra no R, estamos em condições de incluir uma tabela na base de dados.
Primeiramente, vamos conectar-nos à base:
conn <- DBI::dbConnect(RPostgres::Postgres(), dbname="datasets")
Estou admidindo com o código acima que você está usando o R na mesma máquina do Postgres, usando o usuário postgres
e dispensou o uso de senha para conexão local.
Vamos enviar o dataframe mtcars para a base de dados. O exemplo do mtcars não é muito feliz porque ele poderia ser chamado do próprio R quando rodado no Postgres, mas apenas a título de exemplo, iremos assumir que ele seja qualquer outro data.frame.
DBI::dbWriteTable(conn,"tabela", mtcars)
De volta ao Postgres
Mostraremos num próximo tutorial como realizar os procedimentos a seguir sem sair do R, mas o propósito deste tutorial é justamente ilustrar como podemos chamar o R do Postgres. Assim, faremos tudo no Postgres mesmo.
Voltando para o shell, vamos conectar-nos à base datasets:
sudo -u postgres psql datasets
Verifique se a tabela chamada “tabela” se encontra na base de dados:
\d+ -- ou
\d+ tabela
Preparando o terreno
Vamos criar uma tabela que servirá de referência para receber os resultados de uma regressão linear. Veja que as colunas são as mesmas do tibble
retornado pela função tidy
do pacote broom
, com a diferença de que os pontos foram substituídos pelo sublinhado e os nomes das colunas passados para o português.
create table modelo (termo text, estimativa float8, erro_padrao float8, estatistica float8, p_valor float8);
Criando uma função plr
Enfim estamos em condições de criar uma função no PostgreSQL que chama o R para rodar uma regressão linear em uma tabela contida no próprio Postgres:
CREATE OR REPLACE FUNCTION lm_teste() RETURNS SETOF modelo AS
$$
base <<- pg.spi.exec('select mpg, wt, qsec, am from tabela')
df <- lm(mpg ~ wt + qsec + factor(am), data=base)
df <- broom::tidy(df)
names(df) <- c('termo','estimativa','erro_padrao','estatistica','p_valor')
df <- dplyr::mutate_at(df,dplyr::vars(2:5), ~round(.,2))
return(df)
$$
language 'plr';
Note que o esqueleto da função é o mesmo para qualquer outra função do PostgreSQL. A diferença é que, para importar um objeto da base de dados para nossa função, devemos usar a função pg.spi.exec
.
Rodando a regressão linear
Agora ficou fácil. Basta chamar a função e ver os resultados:
select * from lm_teste();
datasets=# select * from lm_teste();
termo | estimativa | erro_padrao | estatistica | p_valor
-------------+------------+-------------+-------------+---------
(Intercept) | 9.62 | 6.96 | 1.38 | 0.18
wt | -3.92 | 0.71 | -5.51 | 0
qsec | 1.23 | 0.29 | 4.25 | 0
factor(am)1 | 2.94 | 1.41 | 2.08 | 0.05
(4 rows)
Vantagens
Eu apontaria duas principais vantagens em usar o plr:
1 - Uma vez que a base se encontra no PostgreSQL, você não precisa mais transferi-la para o R a fim de rodar o modelo e retornar o resultado ao PostgreSQL. Essa viagem dos dados torna-se dispensável. No exemplo mostrado, porém, a base irá para uma sessão do R de qualquer forma. Veremos como solucionar isso em tutoriais futuros.
2 - Você pode continuar trabalhando no R, enquanto seu modelo roda no PostgreSQL. Se o modelo tomar horas, este se torna um problema menor.