Exemplos de scripts para reorganizar dados

Seguem mais uma rotina em shell script (e R) para editar um arquivo CSV no formato desejado. O outro conjunto de scripts, com comandos para baixar um arquivo e converter de XLS para CSV, pode ser visto no post Como baixar dados em planilha e arrumar para arquivo de texto. O arquivo aqui utilizado pode ser o encontrado no site do ONS - como ele tem macros que referenciam o conteúdo das células, ele precisa ser aberto no Libre Office e salvo manualmente no formato CSV.

- split_files.sh

O algoritmo do script abaixo deve criar um arquivo para cada posto (partindo de um arquivo só com todos os dados) e chamar outro script (em R) para reorganizar os dados de cada arquivo. Para cada linha do arquivo "vazoes.csv", ele busca o código do posto, que é o único elemento que está entre parênteses no documento. Se essa busca não retornar vazio, significa que encontrou a identificação de algum posto. O conteúdo das linhas sempre é gravado em um arquivo de saída. O truque para não sobrescrever e gerar um arquivo igual ao original é usar a variável "n" como identificação do posto para nomear o arquivo de destino. Assim, toda a saída é direcionada para um arquivo cujo nome é definido pela variável "n", que identifica de qual posto são os dados.

#!/bin/bash
# Ficar atento para possíveis alterações na formatação, como pontos separando milhar

oldIFS=$IFS  # backup do separador de campo
IFS=$'\n'     # novo separador de campo, o caractere de fim de linha
for linha in $(cat vazoes.csv); do
	# pegar campo entre parênteses para entrar como nome de arquivo "posto_$n.csv"
	n=$(echo $linha | grep -o -P '(?<=\().*(?=\))') if [ ! -z "$n" ]; then echo $n filename='temp_'$n'.txt' fi echo $linha >> $filename
done

# Comando alternativo às linhas anteriores
#awk '/,,,,,,,,,,,,,/{filename=NR".txt"}; {print >filename}' vazoes.csv

# Formatar para "Data,Vazao"; 1931-01-01,178 (p. ex)
for file in $(ls $DIR/temp_*.txt); do
	echo $file
	n=$(echo $file | grep -o [0-9]*)
	Rscript $DIR'/split_columns.R' $file $DIR'/posto_'$n'.csv'
done
rm temp_*.txt

O comando alternativo comentado no código é uma opção para separar o conteúdo do arquivo original em vários arquivos conforme um padrão de texto. Nesse caso, o padrão que aparece é uma sequência de 13 vírgulas: tudo o que está a partir desse padrão até o seguinte (excluindo esse) será impresso em um arquivo cujo nome terá o número da linha seguido de ".txt". Como nesse caso a numeração dos postos segue outra sequência numérica, foi adotada a solução acima para o nome do arquivo já ficar com a identificação do posto.

- split_columns.R

O arquivo de entrada possui dados onde as colunas identificam os meses e a média anual (última coluna, que deve ser desconsiderada), enquanto que as linhas representam os anos e mais três estatísticas mensais (últimas linhas, que devem ser desconsideradas). A ideia desse script é de, primeiro, ler o arquivo CSV pulando a primeira linha e considerando a segunda como o cabeçalho da tabela, gravada com o nome "matriz" - nesse ponto, poderia ser utilizada a primeira coluna (com ano e identificações de estatística) como nome das linhas, mas essa ideia só tive depois. Então, é criada uma matriz vazia, chamada de "final", para receber os valores da matriz de dados, chamada "matriz", no formato "Data,Vazao", ou seja, "1931-01-01,178", por exemplo. Finalmente, essa matriz final é gravada no aquivo com o número de identificação do posto.

# Recebe variáveis
args <- commandArgs(trailingOnly = TRUE)
file_in = args[1]
file_out = args[2]

# Ler arquivo
matriz = read.csv(file_in, skip=1, header=TRUE, sep=",")
# Criar variaveis
dia = "01"
nlinhas = (nrow(matriz)-3)*12
final = matrix(nrow = nlinhas, ncol = 2)
n = 1
# Gravar tabela final com dados da matriz
for (linha in 1:(nrow(matriz)-3)){
	ano = matriz[linha,1]
	for (coluna in 2:(ncol(matriz)-1)){
		mes = coluna - 1
		anomesdia = paste(ano,sprintf("%02d",mes),dia,sep='-')
		dado = matriz[linha,coluna]
		final[n,1] = anomesdia
		final[n,2] = dado
		n = n + 1
	}
}
colnames(final) = c('Data','Vazao')
# Gravar arquivo
write.table(final, file_out, quote = FALSE, row.names = FALSE, col.names = TRUE, sep = ',')

Note que, para forçar o mês ser gravado sempre com dois dígitos (com um zero à esquerda), é utilizado o comando "sprintf("%02d",mes)".

Gravar um arquivo XLS por linha de comando

O gnumeric, gerenciador de planilhas do projeto GNOME, possui o comando "ssconvert" para gravar arquivo .xls e .xlsx a partir de arquivos .csv. Para isso, instale o gnumeric (comando "sudo apt-get install gnumeric") caso não tenha o programa já instalado. Para converter o arquivo exemplo.csv para XLS, basta usar o comando "ssconvert exemplo.csv exemplo.xls".

Também é possível converter vários arquivos CSV como sendo planilhas de um mesmo arquivo XLS usando a opção "--merge-to=exemplo.xls". O nome de cada arquivo será o título da planilha dentro do arquivo, então fica a dica de renomear os arquivos antes de executar o comando. Mais opções no manual do ssconvert.

Compartilhe o link desse texto, mas se for copiar algum trecho, cite a fonte. Valorize nosso trabalho.
Mais informações na licença de uso do site.

Um Pingback/Trackback