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.
2 comments