Como abrir planilhas Excel e arquivos de coluna fixa no R

Com o objetivo de otimizar os arquivos de entrada de algoritmos automatizados, você pode usar ferramentas no R para abrir um arquivo XLSX (do Microsoft Excel) ou um arquivo com colunas fixas e trabalhar com eles, salvando o resultado e um arquivo de saída. A algum tempo, fiz um post sobre como baixar dados em planilha e arrumar para arquivo de texto, misturando shell script e R. Já no post atual, tudo é feito no R.

O pacote “readxl” do R permite abrir uma planilha no formato XLSX e guardá-la em uma data frame. Caso tenha mais de uma planilha no mesmo arquivo, sua ordem deve ser especificada como um parâmetro de entrada após o nome do arquivo. A função utilizada é a “read_excel()”.

Para abrir um arquivo de colunas com largura fixa, basta usar o comando “read.table()” e acrescentar a opção “strip.white=TRUE” para ele considerar os caracteres de espaço como a separação entre colunas. Note que, se existir algum campo com o caractere espaço dentro (mesmo que dentre aspas), essa dica não vai funcionar.

Caso queira salvar o arquivo usando colunas de largura fixa, pode-se usar o pacote “gdata”. A função utilizada é a “write.fwf()”, que pode receber como argumentos de entra a data frame a ser gravada, o nome do arquivo de saída, a largura (em caracteres) de cada coluna, se vai imprimir os nomes das colunas ou não, e até o alinhamento (esquerda, direita, etc).

Outro pacote utilizado aqui é o “sqldf”, que permite executar queries SQL de busca nas tabelas como se fossem parte de um banco de dados MySQL. Seu principal argumento de entrada é uma string com a query a ser executada. Como ele não altera diretamente nenhuma tabela diretamente, caso queria fazer alguma alteração de valor nos campos (como através do comando UPDATE), é preciso retornar a tabela toda na mesma execução, através de SELECT. Veja o exemplo:

sql1 = sprintf("UPDATE met_prev SET prec = '%s' WHERE ano = '%s' AND mes = '%s'", nova_prec, ano, mes)
sql2 = "SELECT * from met_prev"
met_prev = sqldf(c(sql1,sql2))

A variável “prec” é atualizada para um dado mês e ano. Em seguida, a tabela toda é selecionada e atualiza a variável “met_prev”, que possuía a tabela original.

Exemplo

A rotina a seguir mostra um exemplo da aplicação dessas funções. O arquivo “input.dat” possui dados gravados em colunas de largura fixa e sem cabeçalho. Esse arquivo é aberto para obter a 2ª coluna, que possui os números dos pontos a serem considerados. Também são abertos dois arquivos no formato XLSX (primeira planilha de “arq1.xlsx” e “arq2.xlsx”), nos quais serão procurados os números dos pontos já carregados na memória (variável “pontos”) na coluna 4 e salvo o valor dessa linha, mas na coluna 9 ou 11, conforme o caso.

Após salvar os valores das três situações em três variáveis, é verificado se dois desses valores são válidos (ou seja, não são NaN, nem infinito) através da função is.finite(), após terem sido deledionados de uma data frame de tamanho 1×1. Caso já tenha sido criada a data frame “df”, é criada a linha “de” para ser adicionada a “df”; caso contrário, é criada a data frame “df” com uma linha contendo a mesma estrutura de colunas. As colunas também recebem nomes através da função “names()”.

Após montar a data frame “df” linha por linha, ela é gravada como o arquivo “output.dat” com colunas de largura fixa (8 caracteres cada), sem cabeçalho e alinhada pela direita.

## Definindo bibliotecas
end_libs="~/Rpacks"
# Pacote para ler XLSX e suas dependencias
suppressPackageStartupMessages(require(tibble,lib=end_libs))
suppressPackageStartupMessages(require(readxl,lib=end_libs))
# Pacote para usar queries SQL e suas dependencias
suppressPackageStartupMessages(require(tcltk,lib=end_libs))
suppressPackageStartupMessages(require(proto,lib=end_libs))
suppressPackageStartupMessages(require(gsubfn,lib=end_libs))
suppressPackageStartupMessages(require(RSQLite,lib=end_libs))
suppressPackageStartupMessages(require(sqldf,lib=end_libs))
# Pacote para imprimir em coluna fixa
suppressPackageStartupMessages(require(gdata,lib=end_libs))

# Montar lista de IDs de pontos
tabela = read.table("input.dat", header=FALSE, strip.white=TRUE)
pontos = tabela[,2]

# Ler arquivos Excel e guardar em data frame
arq1 = read_excel("arq1.xlsx", 1)
arq2 = read_excel("arq2.xlsx", 1)

# Loop de pontos
for (id in pontos) {
	# Variável do arq1 (caso 7)
	query = paste("SELECT X__9 FROM arq1 WHERE X__4 = '",as.character(id),"'",sep = "")
	var1_7 = sqldf(query,stringsAsFactors = FALSE)
	var1_7 = as.numeric(var1_7[[1]][1])
	# Variável do arq2 (caso 7)
	query = paste("SELECT X__9 FROM arq2 WHERE X__4 = '",as.character(id),"'",sep = "")
	var2_7 = sqldf(query,stringsAsFactors = FALSE)
	var2_7 = as.numeric(var2_7[[1]][1])
	# Variável do arq2 (caso 3)
	query = paste("SELECT X__11 FROM arq2 WHERE X__4 = '",as.character(id),"'",sep = "")
	var2_3 = sqldf(query,stringsAsFactors = FALSE)
	var2_3 = as.numeric(var2_3[[1]][1])
	# Se os valores obtidos forem válidos, acrescentar linha na tabela
	if (is.finite(var2_7) && is.finite(var2_3)) {
		# Pegar o menor valor entre as duas variáveis
		var2_min = pmin(var2_7, var2_3)
		# Criar tabela (se não existir) e acrescentar linhas (append)
		if (exists('df') && is.data.frame(get('df'))){
			de = data.frame(id,var1_7,var2_7,var2_3,var2_min)
			names(de) = c("id","var1_7","var2_7","var2_3","var2_min")
			df = rbind(df,de)
		} else {
			df = data.frame(id,var1_7,var2_7,var2_3,var2_min)
			names(df) = c("id","var1_7","var2_7","var2_3","var2_min")
		}
	} else {
		print(paste(id,"sem dados"))
	}
}

# Salvar tabela em arquivo com colunas fixas
write.fwf(df, file="output.dat", width=c(8,8,8,8,8), colnames=FALSE, justify="right")

A função “suppressPackageStartupMessages” é usada somente para suprimir mensagens iniciais quando os pacotes são chamados.

Compartilhe :)

2 comments

Leave a Reply

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.