Como a principal motivação para o uso do software R está na análise de dados e exibição gráfica de resultados é necessário ter formas eficientes para promover a leitura de dados para dentro de nosso ambiente.
Edição básica de tabelas
Já vimos que objetos como data frames
podem ser editados por meio dos comandos edit(objeto)
ou fix(objeto)
que abrem uma janela para a alteração em forma de grade, permitindo inclusive a inserção de novos campos ou a alteração de nomes dos campos já existentes. Esta pode ser uma boa estratégia para se fazer pequenas alterações nas tabelas.
Outra função usada para leitura de dados do usuário ou à partir da leitura de um arquivo é scan()
.
scan(file = "", what = double(), n = -1, sep = "")
Valores listados para os parâmetros são default. Existem muitos outros parâmetros.
file = ""
indica que a leitura será feita do teclado. Se file = "arquivo"
este arquivo
será lido.
what
indica o tipo de dado a ser lido. what=character()
significa que strings serão lidas.
n
é o número de dados que serão inserido. n = -1
significa um número ilimitado. Neste caso a inserção (para n=-1) termina com dois <ENTER> seguidos.
sep = ""
é o tipo de separador esperado. O default é um espaço em branco.
> x <- scan(n=3) # insere 3 valores do teclado 1: 12 2: 23 3: 34 Read 3 items > x [1] 12 23 34
Arquivos CSV
Para a leitura de bases de dados mais extensas outras formas estão disponíveis. Uma delas consiste em realizar a leitura de um arquivo csv
(valores separados por vírgula, em inglês comma separated values). Este tipo de arquivo consiste em uma lista de linhas, cada uma delas contendo um número constante de valores, separados por vírgula (ou outro sinal). Estes arquivos podem ser lidos por gerenciadores de planilhas tais como o Excel ou o CALC, do Libre Office. Eles podem também ser gerados por estes aplicativos.
Vamos criar um arquivo para efeito de aprendizado dessa importação de dados. Em um editor de texto ASCII qualquer digitamos os valores seguintes:
id, Nome, Sobrenome, Idade, Sexo 1, Marta, Rocha, 24, F 2, Pedro, Souza, 12, M 3, José, Marciano, 15, M 4, Joana, Santos, 21, F 5, Lucas, Pereira, 20, M
O espaçamento entre os campos não é necessário. Digamos que gravamos este arquivo com o nome alunos.csv
na pasta de trabalho em uso (ou em outra qualquer).
Estes dados podem ser lidos com o comando read.table
:
read.table("nomeArquivo.csv", header=TRUE, sep=",", dec=".")
Aqui o parâmetro header=TRUE
indica que a primeira linha do arquivo contém títulos para as colunas, sep=","
indica que as valores estão separados por vírgula (poderiam estar separados por outro caracter, como “;”) e dec="."
indica que o ponto é o separador numérico de decimais.
Se o arquivo não estiver na pasta de trabalho atual o nome completo ("caminho/nomearquivo.csv"
) deve ser fornecido.Para a conveniência do usuário, diversas funções do R são acompanhadas de outras com nomes diversos que realizam as mesmas operações mas usam parâmetros default diferentes. É o caso de read.table()
e read.csv()
.
Consulte a ajuda para ver quais são estes parâmetros.
Por default ítens numéricos são lidos como variáveis numéricas e texto como fatores, embora este comportamento possa ser alterado se necessário. A primeira linha (o cabeçalho) alimenta os valores de nomes de colunas.
> dir()
[1] "alunos.csv"
> alunos <- read.table("alunos.csv", header=TRUE, sep=",", dec=".")
> alunos
id Nome Sobrenome Idade Sexo
1 1 Marta Rocha 24 F
2 2 Pedro Souza 12 M
3 3 José Marciano 15 M
4 4 Joana Santos 21 F
5 5 Lucas Pereira 20 M
> class(alunos)
[1] "data.frame"
> fix(alunos) # permite a edição em uma tabela de alunos
> names(alunos) # lista propriedades names
[1] "id" "Nome" "Sobrenome" "Idade" "Sexo"
> dim(alunos) # dimensões da lista (5 linhas com 5 campos)
[1] 5 5
> alunos[1,] # primeira linha da lista
id Nome Sobrenome Idade Sexo
1 1 Marta Rocha 24 F
> # O parâmetro row.names
permite usar uma coluna para nomear as linhas:
> outroAlunos <- read.table("alunos.csv", header=TRUE, row.names="id", sep=",")
> outroAlunos
N Nome Sobrenome Idade Sexo
1 Marta Rocha 24 F
2 Pedro Souza 12 M
3 José Marciano 15 M
4 Joana Santos 21 F
5 Lucas Pereira 20 M
Em muitos casos precisamos executar a operação inversa: exportamos os dados em uma tabela para um arquivo csv
para transferir dados e utilizá-los em outro aplicativo. Para isso usaremos, a seguir, a função write.csv()
> # Para recordar, criamos uma nova tabela, semelhante àalunos
: > alunos2 <- data.frame( id =1:5, Nome = c("Marta","Pedro","José","Joana","Lucas"), Sobrenome = c("Rocha","Souza","Marciano","Santos","Pereira"), Idade = c(24, 12, 15, 21, 20), Sexo = c("F", "M","M", "F", "M") ) > # Para gravar esta tabela em disco, como um arquivocsv
: > write.csv(alunos2, file="alunos2.csv") > # Se o parâmetro file for omitido a saída é para o console > write.csv(alunos2) "","id", "Nome", "Sobrenome", "Idade","Sexo" "1", 1, "Marta", "Rocha", 24, "F" "2", 2, "Pedro", "Souza", 12, "M" "3", 3, "José", "Marciano", 15, "M" "4", 4, "Joana", "Santos", 21, "F" "5", 5, "Lucas", "Pereira", 20, "M"
Para gravar o objeto alunos2
(uma lista) para uso futuro usamos save()
. O objeto pode ser recuperado para o projeto através da função load()
.
> save(alunos2, file="alunos2.Rdata") > dir() # Para verificar quais são os aqruivos na pasta [1] "alunos.csv" "alunos2.Rdata" > rm(alunos2) # alunos2 não existe mais na sessão > load('alunos2.Rdata') # recupera alunos2 > str(alunos2) 'data.frame': 5 obs. of 5 variables: $ id : int 1 2 3 4 5 $ Nome : Factor w/ 5 levels "Joana","José",..: 4 5 2 1 3 $ Sobrenome: Factor w/ 5 levels "Marciano","Pereira",..: 3 5 1 4 2 $ Idade : num 24 12 15 21 20 $ Sexo : Factor w/ 2 levels "F","M": 1 2 2 1 2
Alternativamente, podemos ler uma variável de texto para dentro de uma tabela.
> dados <- " idade sexo altura 13 F 1.25 15 F 1.60 10 M 1.40 " > tabela <- read.table(header=TRUE, text=dados) > str(tabela) 'data.frame': 3 obs. of 3 variables: $ idade : int 13 15 10 $ sexo : Factor w/ 2 levels "F","M": 1 1 2 $ altura: num 1.25 1.6 1.4
Nos exemplos anteriores os tipos das colunas foram inferidos à partir dos dados lidos. Os campos de texto foram convertidos em fatores. O parâmetro colClasses
permite que sejam informados previamente o tipo de cada coluna lida.
> alunosNotas <- " id| aluno |nota |bolsista 1 | Marco | 5.2 |sim 2 | Ana | 7.5 |nao 3 | Celia | 2.5 |sim" > notas <- read.table(header=TRUE, text=alunosNotas, row.names="id", sep="|", colClasses=c("numeric", "character", "numeric", "character")) > str(notas) 'data.frame': 3 obs. of 3 variables: $ aluno : chr " Marco " " Ana " " Celia " $ nota : num 5.2 7.5 2.5 $ bolsista: chr "sim" "nao" "sim" > # A coluna bolsista foi importada como strings. > # Para transformá-la em uma coluna de valores lógicos podemos fazer > notas$bolsista <- notas$bolsista=="sim" > str(notas) 'data.frame': 3 obs. of 3 variables: $ aluno : chr " Marco " " Ana " " Celia " $ nota : num 5.2 7.5 2.5 $ bolsista: logi TRUE FALSE TRUE
Se um arquivo *.csv
se encontra na web, disponível através de protocolo http
(como o arquivo na url usada abaixo, do site Sample Videos) podemos usar sua url
:
> url <- "https://www.sample-videos.com/csv/Sample-Spreadsheet-10-rows.csv" > dadosCsv <- read.csv(url) > # A função carrega um data frame em dadosCsv
Se a página da web usa o protocolo https
(mais seguro que o anterior) podemos usar o pacote RCurl
. Como exemplo vamos baixar um arquivo diponibilizado pela cidade de Seattle, EUA (King County Open Data), contendo dados sobre animais de estimação perdidos:
> install.packages("RCurl") > library (RCurl) > url <- "https://data.kingcounty.gov/api/views/yaai-7frk/rows.csv?accessType=DOWNLOAD" > dw <- getURL(url) > dados <- read.csv (text = dw) > class(dados) [1] "data.frame" > View(dados)
Com frequência dados baixados da internet contém falhas como, por exemplo, uma entrada em texto em uma coluna numérica. Estes dados precisam ser visualizados e tratados antes de uma análise de sua informação. Podemos vizualizar estes dados de forma gráfica usando a função View()
que exibe em tabela um dataframe
.
Importando planilhas
xlsx
depende para seu funcionamento dos pacotes rJava
e xlsxjars
, bem como uma instalação funcional do Java em seu computador.Para importar uma planilha do Excel ou Libre Office Spreadsheet podemos exportar estes dados para um arquivo *.csv
e importá-lo usando as técnicas já descritas. Alternativamente é possível importar diretamente estas planilhas usando o pacote xlsx
, que deve ser instalado antes do uso. Planilhas podem ser importadas com as funções read.xlsx
e read.xlsx2
que têm a seguinte sintaxe:
read.xlsx(file, sheetIndex, sheetName=NULL, rowIndex=NULL, startRow=NULL, endRow=NULL, colIndex=NULL, as.data.frame=TRUE, header=TRUE, colClasses=NA, keepFormulas=FALSE, encoding="unknown", password=NULL, ...) read.xlsx2(file, sheetIndex, sheetName=NULL, startRow=1, colIndex=NULL, endRow=NULL, as.data.frame=TRUE, header=TRUE, colClasses="character", password=NULL, ...)
Argumento | Descrição |
---|---|
file | arquivo (com caminho) a ser lido. |
sheetIndex | número da planilha dentro da pasta de trabalho. |
sheetName | nome da planilha. |
rowIndex | vetor numérico indicando linhas a serem extrarídas. Se NULL todas as linhas, exceto se startRow, endRow são especificados. |
colIndex | vetor numérico indicando colunas a serem extrarídas. Se NULL todas as colunas. |
as.data.frame | valor lógico. Se TRUE os dados serão montados em um data.frame. Se FALSE, uma lista, com um elemento por coluna. |
header | valor lógico indicando que a primeira linha contém os nomes das colunas. |
colClasses | (read.xlsx) vetor de strings com a classe de cada coluna. |
keepFormulas | valor lógico. Se TRUE as fórmulas do excel são mostradas como texto e não avaliadas. |
encoding | codificação para strings na planilha. |
startRow | numérico, especificando índice da 1ª linha. (Ativo se rowIndex=NULL). |
endRow | numérico, especificando índice da última linha. Se NULL, todas as linhas. (Ativo se rowIndex=NULL). |
password | senha para a pasta de trabalho. |
… | outros argumentos para a data.frame. Ex. stringsAsFactors |
A função read.xlsx
procura adequar o tipo lido com o da planilha de acordo com cada coluna, preservando o tipo de dado lido.
read.xlsx2
é mais rápida, adequada para ser usada em planilhas muito grandes, acima de 100 mil células. Ambas podem ser usadas para ler arquivos *.xlsx
ou *.xls
.
> library(xlsx) > xlFrame <- read.xlsx("planilha.xlsx",1, header=TRUE); xlFrame Data Local Crédito Débito 1 43223 Casa Coral 1002.56 65.45 2 43224 Fornecedor 1 23.34 NA 3 43225 Cliente 2 24.34 33.00 4 43226 Fornecedor 2 15.23 54.00 > # Valor não existente na planilha foi lido como 'NA' > # A data foi lida como um campo numérico.
Gravando dados em uma planilha Excel
As funções write.xlsx
e write.xlsx2
podem ser usadas para gravar dados de uma tabela em uma pasta de trabalho Excel. A segunda delas atinge uma performance melhor para planilhas longas, acima de 100 mil células.
Elas têm a sintaxe:
write.xlsx(x, file, sheetName="Sheet1", col.names=TRUE, row.names=TRUE, append=FALSE, showNA=TRUE, password=NULL)write.xlsx2(x, file, sheetName="Sheet1", col.names=TRUE, row.names=TRUE, append=FALSE, password=NULL, ...)
São seus argumentos:
Argumento | Descrição |
---|---|
x | data.frame a ser escrito como pasta de trabalho. |
file | arquivo (com caminho) a ser escrito. |
sheetName | nome da planilha. |
col.names | valor lógico. Se TRUE os nomes das colunas de x são escritos no arquivo. |
row.names | valor lógico. Se TRUE os nomes das linhas de x são escritos no arquivo. |
append | valor lógico. Se TRUE o arquivo é lido no disco e incrementado. |
showNA | valor lógico. Se FALSE valores NA são gravados em branco. |
password | senha para a pasta de trabalho. |
… | outros argumentos passados para addDataFrame (no caso de read.xlsx2). |
Para exibir o comportamento destas funções usamos o data.frame USArrests
(que vem instalado no pacote básico de R).
Primeiro criamos uma planilha com nome USA-ARRESTS. Depois gravamos em outra planilha na mesma pasta o dataframe alunos
que temos carregado em nossa sessão.
> write.xlsx(USArrests, file="pastaTrabalho.xlsx", sheetName="USA-ARRESTS", append=FALSE) > write.xlsx(alunos, file="pastaTrabalho.xlsx", sheetName="alunos", append=TRUE)
O resultado é a gravação, em disco, de uma pasta de trabalho com duas planilhas com nomes USA-ARRESTS e alunos.
Existem outros pacotes destinados à manipulação de arquivos de planilhas. Entre eles citamos os pacotes XLConnect
e openxlsx
. Este último não depende de Java.
Manipulação de arquivos XML
XML
(Extensible Markup Language) é um formato de transmissão de dados bastante usado na internet e computação em geral, usando apenas texto puro (ASCII). Ele contém tags de marcação que descrevem a estrutura dos dados.
Instale o pacote usando
install.packages("XML")
No R se pode ler e escrever em arquivos XML
usando o pacote "XML"
. Para experimentar com a biblioteca usaremos um arquivo ASCII com o conteúdo abaixo, que gravaremos no disco com o nome livros.xml
.
<biblioteca> <livro> <id>1</id> <titulo>A Dança do Universo</titulo> <autor>Marcelo Gleiser</autor> </livro> <livro> <id>2</id> <titulo>DNA: O Segredo da Vida</titulo> <autor>James D. Watson</autor> </livro> <livro> <id>3</id> <titulo>Uma breve história do tempo</titulo> <autor>Stephen W. Hawking</autor> </livro> <livro> <id>4</id> <titulo>Como a mente funciona</titulo> <autor>Steven Pinker</autor> </livro> <livro> <id>5</id> <titulo>A falsa medida do homem</titulo> <autor>Stephen Jay Gould</autor> </livro> <livro> <id>6</id> <titulo>O último teorema de Fermat</titulo> <autor>Simon Singh</autor> </livro> </biblioteca>
O código seguinte carrega este arquivo para um objeto do R e o manipula.
> # Carrega os pacotes necessários > library("XML", "methods") > # Importa dados para um objeto de R > livros <- xmlParse(file="livros.xml", encoding="UTF8" ) > class(livros) # "XMLInternalDocument" "XMLAbstractDocument" > print(livros) <biblioteca> <livro> <id>1</id> <titulo>A Dança do Universo</titulo> <autor>Marcelo Gleiser</autor> </livro> ... (outros 5 livros) </biblioteca> > xmlTop <- xmlRoot(livros) # node principal > class(xmlTop) [1] "XMLInternalElementNode" "XMLInternalNode" "XMLAbstractNode" > xmlName(xmlTop) # nome do node principal [1] "biblioteca" > xmlSize(xmlTop) # tamanho do node principal [1] 6 > xmlName(xmlTop[[1]]) # nome do primeiro node [1] "livro" > xmlSize(xmlTop[[1]]) # tamanho do primeiro node [1] 3 > print(xmlTop[[2]]) # exibe o segundo node <livro> <id>2</id> <titulo>DNA: O Segredo da Vida</titulo> <autor>James D. Watson</autor> </livro> > xmlTop[[3]][[2]] # segundo ítem do terceiro node <titulo>Uma breve história do tempo</titulo> > # Dados podem ser recuperados usando-se o nome dos nodes > xmlTop[["livro"]][["autor"]] <autor>Marcelo Gleiser</autor> > # Convert um objeto xml para um dataframe > dfLivros <- xmlToDataFrame(livros) > # Visualiza o dataframe > View(df.livros, "Dataframe Livros")
A função View()
exibe o dataframe como na figura abaixo:
Conexão com banco de dados
Naturalmente, grande parte dos dados a serem analisados estão armazendos em bancos de dados relacionais. R pode se relacionar com diversos dos sistemas de gerenciamento, entre eles os mais populares como SQL Server, Access, MySQL, Oracle, PostgreSQL e SQLite. Existem pacotes que permitem o acesso direto aos drivers nativos destes sistemas e outros que permitem esse acesso via ODBC
ou JDBC
. Desta forma o poder das consultas SQL
amplia bastante o potencial de R na análise de dados.
Usando a interface ODBC
Uma forma comum de acessar bancos de dados de dentro do R é através do pacote RODBC
que permite a conexão com qualquer DBMS (Data Base Management System) que admite conexão com o driver ODBC (como é o caso de todos os sistemas listados acima). Para isso é necessário instalar o driver ODBC apropriado para o banco de dados a ser usado, na plataforma específica. Em seguida se instala o pacote ODBC, usando install.packages("RODBC")
. As funções básicas do pacote são:
Função | Descrição |
---|---|
odbcConnect(dsn,uid=””,pwd=””) | abre uma conexão com o driver ODBC |
sqlFetch(channel,sqltable) | lê uma tabela e a carrega em um data frame |
sqlQuery(channel,query) | submete uma consulta sql e retorna os resultados |
sqlSave(channel,mydf,tablename= sqltable,append=FALSE) | escreve ou atualiza um data frame para tabela da base |
sqlDrop(channel,sqltable) | remove uma tabela do bando de dados |
close(channel) | fecha a conexão |
O pacote RODBC permite a comunicação bidirecional entre R e o banco de dados, que pode ser lido ou alterado. Suponha que um banco de dados possua duas tabelas possua, digamos debito
e credito
. É possível importá-las para dentro de uma sessão fazendo:
> library(RODBC) > conn <- odbcConnect("dsn", uid="usr", pwd="senha") > debito <- sqlFetch(conn, debito) > credito <- sqlQuery(conn, "select * from credito") > close(myconn)
A função sqlQuery()
pode ser usada para a aplicação de qualquer instrução SQL
, permite uma seleção detalhada de variáveis, a criação de novos campos, alteração e inserção de dados no banco.
Usando o pacote DBI
O pacote DBI
(DataBase Interface) fornece outra forma de acesso à DBMS
com suporte à diversos drivers. Entre eles estão os pacotes RJDBC (acesso ao driver JDBC), RMySQL, ROracle, RPostgreSQL e RSQLite.
Para o exemplo que se segue usamos o banco de dados chinook.db
que pode ser baixado no site do SQLite Tutorial.
> library(DBI) > library(RSQLite) > banco <- "chinook.db" > driver <- dbDriver("SQLite") > db <- dbConnect(driver, banco) > # Para exibir qual banco está associado a este objeto: > db <SQLiteConnection> Path: /home/guilherme/Projetos/R/Aprendendo/chinook.db Extensions: TRUE > # Lista de tabelas em chinook.db > dbListTables(db) [1] "albums" "artists" "customers" "employees" "genres" [6] "invoice_items" "invoices" "media_types" "playlist_track" "playlists" [11]"sqlite_sequence" "sqlite_stat1" "sqlite_stat4" "tracks" > # Lista de campos na tabela 'albums' > dbListFields(db, "albums") [1] "AlbumId" "Title" "ArtistId" > sql <- "SELECT AlbumId, Title FROM albums" > db <- dbConnect(driver, banco) > rs <- dbSendQuery(db, sql) > rs <SQLiteResult> SQL SELECT AlbumId, Title FROM albums ROWS Fetched: 0 [incomplete] Changed: 0 > dbColumnInfo(rs) name type 1 AlbumId integer 2 Title character > dbGetStatement(rs) [1] "SELECT AlbumId, Title FROM albums" > albuns <- fetch(rs, n = 5) > albuns AlbumId Title 1 1 For Those About To Rock We Salute You 2 2 Balls to the Wall 3 3 Restless and Wild 4 4 Let There Be Rock 5 5 Big Ones > # Lista de campos na tabela 'artists' > dbListFields(db, "artists") [1] "ArtistId" "Name" > sql <- "SELECT a.Title, b.Name FROM albums a INNER JOIN artists b ON a.ArtistId = b.ArtistId WHERE b.Name LIKE \"Iron%\"" > # O resultado de uma consulta fica armazenado em rs: > rs <- dbSendQuery(db, sql) > # rs tem as seguintes colunas > dbColumnInfo(rs) name type 1 Title character 2 Name character > # rs foi gerada pela consulta (sql query) > dbGetStatement(rs) [1] "SELECT a.Title, b.Name FROM albums a INNER JOIN artists b ON a.ArtistId = b.ArtistId WHERE b.Name LIKE \"Iron%\"" > # O número de colunas alteradas > dbGetRowsAffected(rs) [1] 0 > # Para ler 5 linhas deste resultado > linhas <- fetch(rs, n = 5) > linha Title Name 1 A Matter of Life and Death Iron Maiden 2 A Real Dead One Iron Maiden 3 A Real Live One Iron Maiden 4 Brave New World Iron Maiden 5 Dance Of Death Iron Maiden > dbGetRowCount(rs) # quantas colunas [1] 5 > # Liberando o 'resultset' e a conexão > dbClearResult(rs); dbDisconnect(db)
No código abaixo está mostrado como abrir e manipular um banco de dados PostgreSQL
que deve estar instalado na máquina local. Ele lê uma tabela no banco de nome Notas
que tem uma tabela categorias
com campos id, idPai, categoria
. Em seguida ele usa o data frame alunos
que já está carregado na sessão de R com campos id, Nome, Sobrenome, Idade, Sexo
e grava esta tabela no banco de dados, com nome “alunos”. Finalmente uma consulta de atualização é feita usando a conexão aberta.
> library(DBI) > conn <- dbConnect(odbc::odbc(), driver = "PostgreSQL Unicode", database = "Notas", uid = "nomeUsuario", pwd = "senhaUsuario", host = "localhost", port = 5432) > # Este db possui uma tabela 'categorias' > categorias <- dbReadTable(conn, "categorias") > categorias id idPai categoria 1 10 0 Ciência 2 14 0 Literatura 3 15 14 Ficção Científica 4 11 10 Física ... > # Uma consulta SQL > sql <- "SELECT id, categoria FROM categorias ORDER BY categoria" > categ <- dbSendQuery(conn, sql) > primeiros_3 <- dbFetch(categ, n = 3) # primeiros 3 registros > primeiros_3 id categoria 1 13 Biologia 2 10 Ciência 3 17 Phylos.net > restante <- dbFetch(catg) # lê os demais registros > # Gravando o data frame alunos no banco de dados, com nome "alunos" > # data contém booleano com sucesso da operação > data <- dbWriteTable(conn, "alunos", alunos) > # Uma query de atualização na tabela Categorias > sql <- "UPDATE Categorias SET categoria ='Nova categoria' WHERE id=17" > dbSendQuery(conn, sql) # altera categoria com id = 17
O código a seguir cria um banco de dados virtual (que existe apenas na memória). Ele pode ser útil para teste, para operações provisórias ou mesmo para a criação completa de um banco até que ele esteja pronto para ser gravado em disco.
> library(DBI) > # Cria um banco de dados SQL virtual > conn <- dbConnect(RSQLite::SQLite(), dbname=":memory:") > dbListTables(conn) character(0) > dbWriteTable(conn, "mtcars", mtcars) > dbListTables(conn) [1] "mtcars" > dbListFields(conn, "mtcars") [1] "mpg" "cyl" "disp" "hp" "drat" "wt" [7] "qsec" "vs" "am" "gear" "carb" > dbReadTable(conn, "mtcars") mpg cyl disp hp drat wt qsec vs am gear carb 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 > # Todas as linhas podem ser recuperadas de uma vez: > rs <- dbSendQuery(conn, "SELECT * FROM mtcars WHERE cyl = 4") > dbFetch(rs) mpg cyl disp hp drat wt qsec vs am gear carb 1 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 2 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 3 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 4 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 5 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 (... continua, 32 linhas ...) > dbClearResult(res) > # Lendo o banco por partes > rs <- dbSendQuery(conn, "SELECT * FROM mtcars WHERE cyl = 4") > while(!dbHasCompleted(res)) { parte <- dbFetch(res, n = 5) print(nrow(parte)) } [1] 5 [1] 5 [1] 1 > # Fecha o resultset e a conexão > dbClearResult(rs); dbDisconnect(conn)
Um resumo das funções disponíveis no pacote DBI
estão listadas abaixo. Para uma lista completa, com descrição detalhada de cada função e seus parâmetros consulte a R Database Interface (versão 0.5-1) na página R Documentation.
Função | Descrição |
---|---|
dbDriver | carrega e descarrega drivers |
dbColumnInfo | informa sobre tipos em resultados |
dbExecute | executa uma query e fecha o result set |
dbCallProc | chama uma “stored procedure” |
dbClearResult | limpa uma result set |
dbDisconnect | fecha uma conexão |
dbConnect | cria conexão com uma DBMS |
dbDataType | determina o tipo (SQL) de um objeto |
dbGetStatement | verifica a query associada a um result set |
dbGetRowCount | número de linhas recuperadas até o momento |
dbGetQuery | envia query, retorna resultado e limpa o result set |
dbHasCompleted | status de realização de uma query |
dbGetRowsAffected | número de linhas afetada |
dbExistsTable | booleano, retorna existência da tabela |
dbIsValid | booleano, o DBMS é um objeto válido? |
dbListConnections | lista conexões abertas |
dbListResults | lista resultados pendentes |
dbListFields | lista nomes de campos de uma tabela |
dbSendQuery | executa consulta sobre uma conexão |
dbRemoveTable | remove uma tabela do banco de dados |
dbFetch | recupera registros de consulta já realizada |
transactions | inicia/commit/rollback transações SQL |
sqlAppendTable | insere linhas em uma tabela |
sqlCreateTable | cria uma tabela |
Obtendo dados na Internet
Uma grande quantidade de dados se encontra hoje disponível na internet. Por isso é importante aprender a acessá-los e selecionar aqueles que nos interessam. Esta busca e seleção de dados é denominada web scraping.
Embora existam dados em formato estruturado, como tabelas e até mesmos bancos de dados, muita informação na Web está sob formato não estruturado, como ocorre em muitas páginas de texto HTML. É necessário, portanto, converter essa informação em formatos mais úteis.
Em muitos casos copiar e colar conteúdo de uma página em arquivo local pode ser suficiente. Em arquivos pequenos eles podem ser organizados manualmente e os dados postos em forma de uma tabela, por exemplo com os campos separados por vírgula. Em outros casos uma página pode ser analisada por meio de reconhecimento de padrões, usando expressões regulares ou outro processo.
Muitos sites importantes, como Facebook, Twitter e LinkedIn, fornecem APIs públicas ou privadas, que facilitam a leitura de seus dados. Além disso as páginas da web são alimentadas para os browers dentro de estruturas DOM (Document Object Model), o que facilita a garimpagem de dados.
Se os dados já estão estruturados, sob a forma de um arquivo csv
(por exemplo) então eles podem ser importados para a sessão de R com a função read.table
ou read.csv
. Em seguida eles podem ser manipulados de acordo com a conveniência da análise desejada.
> # Há um arquivo csv de teste no endereço abaixo: > url <- "https://www.sample-videos.com/csv/Sample-Spreadsheet-100-rows.csv" > dados <- read.table(url, sep=",") > # A lista está disponível. Os dois primeiros elementos do campo V3 são: > head(dados$V3, n=2) [1] Muhammed MacIntyre Barry French > # Arquivo sem títulos nas colunas: os campos ficam nomeados V1 até v10 > # Independente da formatação uma página pode ser baixada com: > download.file("https://endereco_url.html", "caminhoOndeSalvar/arquivo.html")
Usando o pacote rvest
rvest
.XPath (XML Path Language) é uma especificação de pesquisa em nodes de um documento
XML
. Existem aplicativos e plugins nos principais browsers para facilitar esta localização. Para o Chrome uma boa ferramenta é o SelectorGadget.No Firefox podemos usar o
inspector
, um ítem de menu em web developer
, que pode ser aberto com CTRL-SHIFT-C
.
Para ler uma página na web e analisar seu conteúdo podemos usar o pacote rvest
. Nele encontramos a função read_html() que retorna um documento XML
que contém toda a informação sobre a página.
Primeiro procuramos uma página na web contendo as informações que desejamos extrair. Para efeito de nosso aprendizado usamos uma páginas simples onde se exibe uma tabela dos estados brasileiros com suas populações e PIBs. Usaremos a página Lista de Estados Brasileiros com população e PIB em Excel. Ignoramos, claro, a possibilidade disponível nessa página de baixar diretamente a tabela em formato Excel. Abrindo esta página no browser abrimos (no Firefox) o web developer, inspector
. Na janela de inspecção procuramos a tabela desejada. Ao movimentar o cursor do mouse sobre o elemento html a tabela fica sombreada. Clique na tabela e pressione o botão direito selecionando copy xpath
. xpath
é um localizador de posição dentro da página, que fica armazenado na área de transfrência. No nosso caso temos xpath = "/html/body/div[3]/div[1]/table"
, indicando que queremos extrair a tabela única dentro do primeiro div, dentro do terceiro div no corpo do documento html. Em seguida baixamos o conteúdo sob forma xml e depois selecionamos o node desejado usando html_nodes(xpath)
.
> library(rvest)
> url <- "http://www.servicos.blog.br/listas/lista-de-estados-brasileiros-com-populacao-e-pib-em-excel/"
> xPath <- "/html/body/div[3]/div[1]/table"
> # O seguinte comando armazena o conteúdo do elemento em xPath como
> populacao <- url %>%
read_html() %>%
html_nodes(xpath=xPath) %>%
html_table()
> # Da forma como foi obtida, populacao
é uma lista com um elemento
> # Este elemento único é a tabela desejada
> populacao <- populacao[[1]]
> View(populacao)
O útimo comando abre a visualização da tabela:
Veremos em breve um pouco mais sobre o funcionamento do pipe %>%
. Por enquanto basta saber que ele faz parte do pacote magrittr
e facilita a notação para operações encadeadas, como a composição de funções:
x %>% f
é equivalente af(x)
x %>% f(y)
é equivalente af(x, y)
x %>% f %>% g %>% h
é equivalente ah(g(f(x)))
Portanto a linha contendo pipes é idêntica aos seguintes comandos:
> pop <- read_html(url)
> pop2 <- html_nodes(pop, xpath=xPath)
> pop3 <- html_table(pop2) # pop3 é o mesmo que populacao
, acima.