Subsections

Scripts para manipular datos

Introducción

Supongamos que queremos escribir un script para ver el número de réplicas por día después del terremoto del 27 de febrero 2010 en Chile, en comparación con el número de días después del terremoto. Para eso, necesitamos:
i)
Tomar el día en el archivo global_seismicity_feb27-apr19_2010.txt como una variable
ii)
Para cada día, calcular el número de réplicas asociadas a el
iii)
Calcular cuantos días después del 27 de febrero esta ella
iv)
Presentar los datos en el terminal, o en otro archivo

Elegir un rango de variables de un archivo

En el archivo global_seismicity_feb27-apr19_2010.txt, la fecha esta dada en la segunda columna:
 more global_seismicity_feb27-apr19_2010.txt | awk '{print $2}'

Aquí, cada día esta representado varias veces, si queremos una lista donde el día esta representado solo una vez,tenemos que usar el comando sort, con la opción -u que significa única:

 more global_seismicity_feb27-apr19_2010.txt | awk '{print $2}' | sort -u

En nuestro script, queremos trabajar con cada día individualmente, y podemos usar el loop for para generar este efecto. El script toma forma ...

#! /bin/bash
for dia in `more global_seismicity_feb27-apr19_2010.txt | awk '{print $2}' | sort -u`
do
#aqui van los comandos para manipular los datos de cada dia
done

Calculando el número de réplicas asociadas con cada día

Desde ahora, tenemos un loop de variables de forma " año/mes/dia "
Para hacer la estructura necesaria para aislar el número de réplicas que vamos a incorporar dentro del script, siempre es útil probar en el terminal con una variable de la forma "2010/03/21" (o equivalente). Para probar, podemos definir:
 dia="2010/03/21"

Asi que ahora, dentro del terminal, la variable día tiene esta definición (pruebe echo $dia).
Para contar el número de sismos asociados con cada día, usamos grep (para eligir las líneas que corespondan al día que queremos) y awk (para contar el número de sismos), por ejemplo:

 more global_seismicity_feb27-apr19_2010.txt | grep 2010/03/21 | awk 'END {print NR}'

y si queremos incorporar la variable $día, usamos:

 more global_seismicity_feb27-apr19_2010.txt | grep $dia | awk 'END {print NR}'

Nota que esto es el número de sismos globales de todos catálogos. Nosotros queremos elegir un catálogo y, solamente el rango de latitudes y longitudes que representan el sismo de Chile. Note que si queremos usar límites sobre el latitud y longitud, necesitamos eliminar las comas en el archivo de datos.
Podemos usar un mapa de la área de ruptura, por ejemplo este:
http://www.tectonics.caltech.edu/slip_history/2010_chile/preliminary/chile10_map.jpg
para estimar el rango de latitudes y longitudes que queremos. Entonces:

more global_seismicity_feb27-apr19_2010.txt | sed 's/,//g' | \\
grep "FINGER/NEIC" | grep $dia | \\
awk '{ if ( $4 > -38 && $4 < -33 && $5 > -75 && $5 < -71 ) print $0}' | \\
awk 'END {print NR}'

es la sentencia para contar el número de sismos del catalogo FINGER/NEIC del día $dia, entre 33$ ^\circ$ y 38$ ^\circ$S y 71$ ^\circ$ y 75$ ^\circ$W. (prúebalo para diferentes días).
Nota:
Cuando tipees esto en un terminal, las instrucciones deben ir en una misma línea. De no ser así, puedes usar $ \backslash$ para indicar que las instrucciones en la línea siguiente son adyacentes a la actual. También se puede usar $ \backslash\backslash$.

Podemos definir este número a ser la variable num:

num=`more global_seismicity_feb27-apr19_2010.txt | \\
sed 's/,//g' | grep "FINGER/NEIC" | grep $dia | \\
awk '{ if ( $4 > -38 && $4 < -33 && $5 > -75 && $5 < -71 ) print $0}' | \\
awk 'END {print NR}'`

y revisarlo con:

 echo $num

Ahora estamos listos para agregar esta línea al script que queremos crear :

#! /bin/bash


# Haciendo un loop sobre cada dia:
for dia in `more global_seismicity_feb27-apr19_2010.txt | awk '{print $2}' | sort -u`
do

# Contando el numero de sismos del catalogo FINGER/NEIC, del dia $dia,
# entre 33 y 38 grados S y 71 y 75 grados W. Esta cantidad de sismos se
# llama num

num=`more global_seismicity_feb27-apr19_2010.txt | sed 's/,//g' \\
| grep "FINGER/NEIC" | grep $dia \\
| awk '{ if ( $4 > -38 && $4 < -33 && $5 > -75 && $5 < -71 ) print $0}' \\
| awk 'END {print NR}'`

done
Notar que $ \backslash\backslash$ es para indicar que la sentencia continúa, función similar a los .. en Matlab.

Calcular el número de días después del 27 de febrero

Seguimos en el terminal con la variable dia="2010/03/21". Queremos cambiar esta fecha para el número de días despues del 27 de febrero. La manera más facil de hacer eso es usando el comando "julday", que ya tenemos en el sistema. Recuerde:
 julday 03 21 2010

lo que nos da el día del año (080) de esa fecha, es decir,
Calendar Date 03 21 2010
Julian Date 080 2010

Ahora, con ayuda del comando julday, vamos a cambiar la variable $dia a un nuevo formato. Para eso reemplazamos los "/" con " ", y reordenamos las columnas. Para sacar los "/", usamos sed.

 echo $dia | sed 's/\// /g'

Ahora cambiamos el orden de las columnas con awk:

 echo $dia | sed 's/\// /g' | awk '{print $2, $3, $1}'

así tenemos la fecha en el formato correcto para poder usarlo con julday. Definimos esto como una variable temporal, en este caso, temp:

 temp=`echo $dia | sed 's/\// /g' | awk '{print $2, $3, $1}'`

Revisa que es lo que se obtiene al tipear echo $temp.
Estamos listo para correr el comando julday con la variable $temp.

 julday $temp

Pero solamente queremos como repuesta el día. Podemos aislarlo elegiendo la línea que solamente contiene la palabra "Julian":

 julday $temp | grep Julian

el día es la tercera columna de esta línea:

 julday $temp | grep Julian | awk '{print $3}'

OK, pero nosotros queremos el número de ese día después del 27 febrero (día 58 - revisalo con julday 02 27 2010). Entonces necesitamos sustraer 58 en el comando awk:

 julday $temp | grep Julian | awk '{print $3-58}'

También queremos este número como una variable, vamos a llamarlo tiempo, para el tiempo en días después del terremoto. En el script:

 tiempo=`julday $temp | grep Julian | awk '{print $3-58}'`

Ahora estamos listos para agregar estas líneas al script que esta en preparación:

#! /bin/bash

for dia in `more global_seismicity_feb27-apr19_2010.txt \\
| awk '{print $2}' | sort -u`
do

# contar el numero de sismos del catalogo FINGER/NEIC, del dia $dia,
# entre 33 y 38 grados sur y 71 y 75 oeste. Llama este numero num

num=`more global_seismicity_feb27-apr19_2010.txt | sed 's/,//g' \\
| grep "FINGER/NEIC" | grep $dia \\
| awk '{ if ( $4 > -38 && $4 < -33 && $5 > -75 && $5 < -71 ) print $0}' \\
| awk 'END {print NR}'`

# extraer el numero de dias despues del terremoto esta la fecha $dia
# llama este tiempo

temp=`echo $dia | sed 's/\// /g' | awk '{print $2, $3, $1}'`
tiempo=`julday $temp | grep Julian | awk '{print $3-58}'`

done

Presentando datos en un terminal

Podemos usar echo para poner los datos en el terminal, es decir:
 echo $tiempo $num

O en el script anterior,

#! /bin/bash

for dia in `more global_seismicity_feb27-apr19_2010.txt \\
| awk '{print $2}' | sort -u`
do

# contar el numero de sismos del catalogo FINGER/NEIC, del dia $dia,
# entre 33 y 38 grados sur y 71 y 75 oeste. Llama este numero num

num=`more global_seismicity_feb27-apr19_2010.txt | sed 's/,//g' \\
| grep "FINGER/NEIC" | grep $dia \\
| awk '{ if ( $4 > -38 && $4 < -33 && $5 > -75 && $5 < -71 ) print $0}' \\
| awk 'END {print NR}'`

# extraer el numero de dias despues del terremoto esta la fecha $dia
# llama este tiempo

temp=`echo $dia | sed 's/\// /g' | awk '{print $2, $3, $1}'`
tiempo=`julday $temp | grep Julian | awk '{print $3-58}'`
# presentar los datos en el terminal

echo $tiempo $num
done

Ahora el script esta listo, 7 líneas de código para obtener lo que queremos.
En los archivos en la página web http://www.mttmllr.com/GMT/ejemplos/, se llama sismos_por_dia.sh.
Hazlo ejecutable y córrelo !

 ./sismos_por_dia.sh

Si queremos poner la salida del script dentro de un nuevo archivo, por ejemplo dia_sismos.txt, usamos:

 ./sismos_por_dia.sh > dia_sismos.txt

Conclusión

El script que hemos creado podría ser hecho a mano en alrededor de una hora (cierto, es solamente un máximo de 2600 líneas para revisar). La ventaja de hacerlo en forma de un script es que, si es necesario, se puede cambiar facilmente el catalogo usado, los límites de latitud y longitud, poner un límite sobre magnitud, etc. También, se puede aplicar eso a diferentes grupos de datos, diferentes catalogos, etc., con poca revisión. Finalmente, con el conocimiento de manipular datos así, usando siempre los mismos comandos como sed, grep, awk y sort, se puede trabajar con cualquier set de datos seguro en el conocimiento de que no importa el formato, se puede extraer la información requerida.
Ahora estamos listo a poner los datos en forma gráfica.

matt 2014-03-19