quinta-feira, 28 de julho de 2016

Como inserir dados no postgresql utilizando o comando COPY

O comando copy do postgresql pode ser utilizado tanto para a entrada quanto para a saída de dados de e para um arquivo texto.
Para agilizar meu trabalho de popular uma tabela de focos de queimadas neste exercício estou utilizando um arquivo CSV como fonte de dados. Note no exemplo abaixo que o arquivo é separado por virgulas e possui um cabecalho na primeira linha.

YYYYMMDD,HHMM,sat,lat,lon,T21,T31,sample,FRP,conf,type
20160401,0013,T,-9.929,151.006,313.3,295.8,490,6.3,43,0
20160401,0016,T,-21.804,149.064,314.0,294.5,571,7.5,48,0
20160401,0017,T,-23.772,151.204,315.0,300.3,827,8.2,0,2

Previamente foi criada uma tabela no banco de dados que apresentam os mesmos campos deste arquivo, e no meu caso ainda existem outros mais que vou popular depois utilizando cruzamento espacial. Por este motivo o comando copy precisa receber uma lista com o nome dos campos que foram definidos na tabela, porém mantendo a ordem do arquivo CSV.

COPY tabela_banco(data,hora,sat,lat,lon,T21,T31,sample,FRP,conf,tipo) 
FROM '/path/to/file.csv' DELIMITER ',' CSV HEADER

Desta maneira o processo é muito rápido.

quarta-feira, 27 de julho de 2016

Ajustes em um arquivo CSV

Tive alguns problemas na conversao de dados que estavam separados por espacos para formatar um arquivo separados por virgula (CSV). Neste arquivo de entrada haviam vários separadores entre um campo e outro e que deveriam ser substituídos por um único, veja o exemplo do dado de entrada:

YYYYMMDD HHMM sat lat lon T21 T31 sample FRP conf type
20160401 0013 T  -9.929  151.006 313.3 295.8  490     6.3  43  0
20160401 0016 T -21.804  149.064 314.0 294.5  571     7.5  48  0
20160401 0017 T -23.772  151.204 315.0 300.3  827     8.2   0  2


Entao, com uso do comando SED:
sed -i.bak 's/ \{1,\}/,/g' MCD14ML.20160?.006.01.txt

Conseguí fazer a conversao dos dados para:

YYYYMMDD,HHMM,sat,lat,lon,T21,T31,sample,FRP,conf,type
20160401,0013,T,-9.929,151.006,313.3,295.8,490,6.3,43,0
20160401,0016,T,-21.804,149.064,314.0,294.5,571,7.5,48,0
20160401,0017,T,-23.772,151.204,315.0,300.3,827,8.2,0,2

Um detalhe deste comando é que o -i faz a substituicao no mesmo arquivo, porém com -i.bak ele adiciona esta extencao no arquivo original mantendo uma cópia.

quarta-feira, 20 de julho de 2016

Manipulação de datas no Python

Sempre que tenho que trabalhar com datas em scripts python utilizo as funções date da seguinte maneira:


import datetime as dt

def calc_lista_datas(datainicial, intervalo):
saida = []
    for d in range(1, intervalo +1):
      d1 = dt.datetime.strptime(str(datainicial), '%Y%m%d')
      d2 = d1 - dt.timedelta(days=int(d))
      print d, d2.strftime('%Y%m%d')
      saida.append(d2.strftime('%Y%m%d'))
    return saida

print calc_lista_datas(20160101, 120)

Isto ajuda a criar uma lista de datas.
Maiores detalhes recomendo:

quarta-feira, 22 de abril de 2015

Como consultar dados dentro de um array no postgresql


dias_com_foco é um array e quero receber todos os eventos dentro de um intervalo de tempo, então preciso saber se para cada registro o valor inicial e final do array de dias está dentro do período do meu interesse.

SELECT evento_id, data, dias_com_foco, duracao, numero_dias_com_foco, numero_focos, parent, geometria
  FROM eventos_requeima
  where dias_com_foco[1] >= '20050101' and dias_com_foco[array_length(dias_com_foco,1)] <= '20051231'
  limit 9;



dias_com_foco[1]= retorna o valor do primeiro elemento do array;

array_length(dias_com_foco,1) = retorna a quantidade de elementos do array, portanto vou conseguir saber qual o último dia registrado.

quarta-feira, 13 de agosto de 2014

Como utilizar case no postgresql

No exemplo apresentado abaixo foi criado um novo campo no retorno da consulta que determina o nível crítico dos eventos de queimadas baseado na duração do evento em dias. Note que foram criados quatro níveis e desconsiderados os eventos com apenas um dia de duração.

Consulta:
select duracao, ST_AsGeoJson(ST_Centroid(the_geom), 3),
    case    when duracao = 2 then 'observação'
        when duracao between 3 and 7 then 'atenção'
        when duracao between 8 and 14 then 'alerta'
        when duracao >= 15 then 'alerta máximo'
    end as nivel
from evento_requeima
where data = 20140730 and duracao > 1;

Retorno:
duracao;geojson;nivel
2;"{"type":"Point","coordinates":[-48.333,-22.731]}";"observação"
2;"{"type":"Point","coordinates":[-46.051,-12.259]}";"observação"
2;"{"type":"Point","coordinates":[-44.891,-7.34]}";"observação"
2;"{"type":"Point","coordinates":[-48.133,-8.785]}";"observação"
10;"{"type":"Point","coordinates":[-57.056,-12.548]}";"alerta"

uma nova referencia encontrei em:
https://popsql.com/learn-sql/postgresql/how-to-write-a-case-statement-in-postgresql/

terça-feira, 15 de julho de 2014

Como utilizar array em bash?

Uma forma de manipular array em BASH pode ser vista abaixo:

lista=("ch1.env" "ch2.env" "ch20.env" "LandSeaMask.env" "SensorZenith.env" "SolarZenith.env")
for ext in "${lista[@]}"
do
echo "arquivos.${ext}"
case "${ext}" in
ch1.env)
#~ echo "nodata=0"
nodata="0"
type="UInt16"
;;
ch2.env)
echo "nodata=0"
nodata="0"
type="UInt16"
;;
ch20.env)
#~ echo "nodata=0"
nodata="0"
type="UInt16"
;;
SensorZenith.env)
#~ echo "nodata=-32767"
nodata="-32767"
type="Int16"
;;
SolarZenith.env)
#~ echo "nodata=-32767"
nodata="-32767"
type="Int16"
;;
LandSeaMask.env)
#~ echo "nodata=221"
nodata="221"
type="Byte"
;;
esac
done

Note que neste caso o operador "@" está controlando a iteração de tal maneira que não é necessário fazer a contagem do total de elementos do array. Porém caso seja necessário utilizar um elemento específico esta forma não atende.

segunda-feira, 23 de junho de 2014

Listagem de diretórios vazios

Para listar os diretórios sem arquivos dentro uma maneira é utilizar o seguinte comando:

  find "/L1_TERRA/2011_01/tif/" -type d -depth -empty -print -exec \rm -rf {} \;

Caso necessário encontrar arquivos vazios o comando é:
find . -maxdepth 1 -empty -type f -exec rm  {} \;


Para apagar arquivos com mais de 30 dias:
find /logs/virs375/log_cron_sh_20* -ctime +30 -exec /bin/rm {} \;