Archivos de la categoría Trucos

Truco Excel. Unir todos los libros en una hoja

unir_excel1

Los trucos Excel referentes a la unión de varios libros en uno tienen mucho éxito en esta web, además era necesario crear una versión que uniera de forma horizontal. No es una unión como la pueda hacer Power Query de anexar tablas con cierto sentido teniendo en cuenta el nombre de las columnas y demás, se trata
de unir todas las celdas de un conjunto de libros de forma horizontal en otro libro resultante como ilustra la figura de arriba. Se unirán todos los campos unos encima de otros independientemente de si se llaman igual o no, si queremos anexar tablas es recomendable usar herramientas más específicas. El funcionamiento es muy sencillo pero
lo vamos a ilustrar con imágenes, el primer paso es pulsar directamente el botón y seleccionar los archivos a unir:

unir_excel2

Ahora sólo tenemos que especificar el archivo de destino, puede existir o no, el proceso lo sustituye:

unir_excel3

Y et voilá! Ya tenemos nuestro archivo resultante Sigue leyendo Truco Excel. Unir todos los libros en una hoja

Truco Excel. Actualizar el filtro de todas las tablas dinámicas de mi libro

Traigo hoy al blog una macro de Excel que nos permite recorrer todas las hojas de un libro y dentro de las hojas nos permite recorrer todas las tablas dinámicas y actualizar un campo. Cuando tenemos un informe que se basa en tablas dinámicas y tiene una actualización mensual nos podemos encontrar con la necesidad de cambiar sólo un elemento de la tabla dinámica para actualizar el informe. Este era el caso de mi compañera, hay una entrada en el blog que ya trataba el tema pero esta nueva macro supone otra vuelta de tuerca sobre ella, no sólo recorre y actualiza todas las tablas dinámicas de una hoja, además lo hace de todo el libro. El código de Visual Basic para Excel es:

Sub filtros()
'Macro creada por www.analisisydecision.es

Dim pt As PivotTable
Dim actual, nuevo As String
    actual = 201701
    nuevo = 201702

For i = 1 To Worksheets.Count

Sheets(i).Activate
For Each pt In ActiveSheet.PivotTables
pt.PivotFields("mes").EnableMultiplePageItems = True
With pt.PivotFields("mes")
.PivotItems(nuevo).Visible = True
.PivotItems(actual).Visible = False
End With
Next pt
Next i

En PivotFields ponemos el nombre del campo que deseamos actualizar. Evidentemente necesitamos esconder el valor actual y poner el valor nuevo recorriendo todas las hojas con el bucle For i = 1 To Worksheets.Count y recorriendo todas las tablas dinámicas de cada hoja con For Each pt In ActiveSheet.PivotTables. Lo que si necesitó estar activo es seleccionar varios elementos del campo que deseamos actualizar y por ello fue necesario poner EnableMultiplePageItems = True no llegamos a entender el motivo pero es importante que “Seleccionar varios elementos” esté activo en la tabla dinámica. Espero que estas pocas líneas de código os sean de utilidad, por aquí han automatizado mucho trabajo manual. Saludos.

Nuevo mapa por provincias en Excel de España. Actualiza los colores en RGB

Mapa_excel_provincias_españa_nuevo

A raiz de esta entrada Otto F. Wagner me envió hace unos meses una nueva versión del conocido mapa de provincias de España en Excel y tenía pendiente subirlo a la web. La diferencia con los anteriores es que puedes elegir el color de inicio y el color de fin jugando con RGB:

Mapa_excel_provincias_españa_nuevo2

------Descarga aquí la nueva versión en formato ZIP-----------

Máximo por registro de una serie de variables carácter en SAS

Un lector del blog preguntaba como obtener el valor máximo dentro de un registro, por fila, de una sucesión de variables caracter; evidentemente la función max no servía porque es específica para variables numéricas. La duda la planteaba del siguiente modo:

Pero tengo una duda que no soy capaz de sacar y no veo ninguna cosa parecida para poder sacarlo, a ver si me puedes ayudar, o si no, pues me dices que no y no hay ningún problema.

Tengo un data de este estilo:
Nombre    Clave1    Clave2    Clave3
Ana             A            A            B
Pepe           H            M            C
Juan           A             A            A

El tema es que necesito calcular el máximo de todas las claves para cada persona, es decir,
Nombre    Clave1    Clave2    Clave3    Max
Ana             A            A            B         B
Pepe           H            M            C        M
Juan           A             A            A         A

Como son letras, no me funciona el max en el proc sql y tampoco sé ninguna función que pueda pasarme las letras a numéricas.
Está claro que la única manera que se me ocurre es transformando las letras a números con un case, hacer el máximo y después transformarlo otra vez a letras, pero es por si sabes alguna manera mejor de hacerlo.

La solución que le planteo se realiza con un array donde seleccionamos sólo las variables clave:

Data datos;
input Nombre $ Clave1 $ Clave2 $ Clave3 $;
datalines;
Ana A A B
Pepe H M C
Juan A A A
;run;

data datos;
set datos;
array cl (*) clave:;
maximo=cl(1);
do i=1 to dim(cl);
if cl(i)>maximo then maximo=cl(i);
end;
drop i;
run;

Inicializamos el máximo al primer elemento del array y vamos recorriendo las variables, si una es mayor que la otra se modifica el máximo. Espero que le sirva a algún otro lector. Saludos.

Truco SAS. Tablas de una librería en una macro variable

Me plantean una duda, como crear un conjunto de datos con las tablas de una librería en sas y posteriormente generar una macro variable con ellos, esta es una entrada análoga a otra del blog pero sirve para recordar como funciona el ODS de SAS y el PROC DATASETS un procedimiento que no he usado habitualmente. Lo primero que vamos a hacer es observar que resultados arroja el PROC DATASETS en su sintaxis más sencilla, ver los contenidos de una librería:

 ods trace on;
proc datasets lib=datos;
quit;
ods trace off;

Recordamos que ODS (Output Delivery System) TRACE ON nos permite ver en la log de SAS los elementos que se obtienen como resultado, en este caso, el más sencillo, tenemos:

Output Added:
-------------
Name: Directory
Label: Directory Information
Template: Base.Datasets.Directory
Path: Datasets.Directory
-------------

Output Added:
-------------
Name: Members
Label: Library Members
Template: Base.Datasets.Members
Path: Datasets.Members
-------------

Evidentemente nos interesa Members para poner en una tabla SAS todos los miembros de la librería:

ods output Members=tablas;
proc datasets lib=datos ;
quit;

Ahora tenemos que meter en una macrovariable todos los elementos del campo name de la tabla SAS que hemos generado. Para ello en vez de emplear el habitual PROC SQL podemos usar una concatenación sobre los valores de name que diera como resultado final la macrovariable con la lista de las tablas: Sigue leyendo Truco SAS. Tablas de una librería en una macro variable

Bucle de fechas con SAS para tablas particionadas

Partimos de un mes inicial hasta un mes final es necesario crear una tabla SAS con dos variables, el inicio del mes y el final del mes. Trabajo con fechas en SAS que todos sabemos es una tarea un "poco ardua".  El título de la entrada también es un poco peculiar pero es la respuesta a la duda que planteaba un lector:

Cogemos dos fechas en formato yyyymmaa
Ej: 20150101 a 2016131

Necesito una salida como la siguiente
20150101   20150131
20150201   20150228
20150301   20150331
20150401   20150430
.

20161101  20161130
20161201  20161231

Pero para que los datos pedidos en este periodo salgan en una tabla por mes con un proc sql  ya diseñado que funciona pero sin particionarlo en una tabla por mes en el log

Se me han ocurrido varias formas de hacerlo pero a continuación os planteo la siguiente. Como referencia hemos de irnos a una entrada anterior del blog, una entrada del 2008 cuando puse en marcha analisisydecision.es

*IDENTIFICA EL ULTIMO DIA DE UN MES;
%macro finmes(fec);
intnx("month",&fec.,1)-1
%mend;


data bucle (drop=i);
do i=201501 to 201612;
    if mod(i,100)=13 then i = i + 88;
else do;
    inicio = i * 100 + 1;
    *PRIMERO TRANSFORMAMOS EN FECHA SAS;
    fin = mdy(mod(i,100),1,int(i/100));
    *DESPUES OBTENEMOS EL ULTIMO DIA DEL MES;
    fin = %finmes(fin);
    *POR ULTIMO LO TRANSFORMAMOS A NUMERICO;
    fin = year(fin)*10000+month(fin)*100+day(fin);
    output;
end;
end;
run;

Lo he hecho de una forma sencilla, se trata de un bucle DO desde el mes inicial a el mes final, en realidad son unos 90 números sin embargo si el módulo del número, el mes, está entre 1 y 12 entonces identifica el primer día del mes e identifica el último día del mes transformando el número a fecha SAS primero, obteniendo el último día después y por último lo transforma del modo más sencillo a un número que pueda entender la partición. Es un bucle SAS susceptible de ser parametrizado. Saludos.

Truco Excel. Repetir un campo a partir de otro que define el número de repeticiones

En realidad necesitamos repetir filas, pero el número de repeticiones está parametrizado por otro campo. Partimos de un rango donde la primera columna es un valor que necesita ser repetido el número de filas que nos indica la segunda columna. Es una duda que planteaba un lector del blog:

Hola, a ver si me podeis ayudar,
quiero repetir cada fila el número de veces que hay en cada celda que le corresponde.
Es decir tengo una variable Nombre (Columna A) y otra Frecuencia (Columna B)
Nombre Frecuencia
A 5
B 8
C 25
D 12
… ….

La idea es repetir la la Fila A, 5 veces, la fila B, 8 veces y así sucesivamente.
En realidad es lo inverso a crear una tabla de frecuencias desde una matriz de datos.

Tenía en la nevera un truco de Excel que puede hacer esta tarea y que también subiré al blog en los próximos días, en realidad esta entrada y la siguiente son modificaciones de un anterior truco Excel que subí al blog. En esta imagen podéis ver lo que hace:

excel_repite_filas

La macro que lo realiza es esta:

Sub rango_columnas2()

Dim rango, celda As Variant
Dim i As Long, j As Long, k As Long
Dim col As Long

rango = Application.InputBox(Prompt:="Seleccione el rango a repetir sin cabeceras", Type:=8)
Set celda = Application.InputBox(Prompt:="Seleccione donde quiere poner los datos", Type:=8)

'Esta es la parte que permite ubicar la salida
celda.Select
k = 0

'Esto recorre el rango
For i = 1 To UBound(rango, 1)
    For j = 1 To rango(i, 2)
        ActiveCell.Offset(k, 0).Value = rango(i, 1)
        k = k + 1
    Next
Next

End Sub

Se ejecutan 2 cuadros con el método Application.InputBox, en el primero seleccionamos el rango de datos sin cabeceras y en el segundo indicamos donde queremos que salgan los datos. Se trata de recorrer el rango y pararse a repetir las primera columna del rango tantas veces como lo indica la segunda columna. Un proceso sencillo con Visual Basic pero que sería interesante replicar con funciones de Excel, en este caso creo que INDIRECTO sería la más adecuada. En el siguiente enlace podéis descargar el ejemplo:

repite_filas

En siguientes fechas daré más vueltas a este bucle para realizar transposiciones de datos. Saludos.

 

Truco Excel. Pasar un rango de varias columnas a una

Macro de Excel que nos permite pasar de varias columnas a una sola. De momento no es una función, es un código que sorprende por su sencillez:

Sub rango_columnas()

Dim rango As Variant
Dim i As Long, j As Long, k As Long
Dim col As Long

rango = Selection.Value

'Esta es la parte que permite ubicar la salida
col = Selection.Column
k = Selection.Row

'Esto recorre el rango y realiza la trasposición
For i = 1 To UBound(rango, 1)
    For j = 1 To UBound(rango, 2)
        Cells(k, col + UBound(rango, 2)).Value = rango(i, j)
        k = k + 1
    Next
Next

End Sub

Este código lo ponéis tal cual en vuestro Excel y os ilustro a continuación sobre su funcionamiento. Lo primero es seleccionar el rango de columnas que deseamos transponer:

varias_columnas_a_una_excel1

Ahora sólo ejecutamos la macro rango_columnas:

varias_columnas_a_una_excel2

Y aparece justo al lado del rango que deseamos transponer a una sola columna:

varias_columnas_a_una_excel3

En este caso el resultado lo obtenemos en la columna F. Jugando con los índices i y j de nuestra macro podremos modificar la forma de la transposición. Me parece una macro útil y por eso lo comparto con vosotros. Saludos.

El paquete de R weatherData para la obtención de datos meteorológicos en España

Tenía pendiente un proyecto con modelos de Lee Carter y el paquete weatherData de R (¡toma!) pero como no lo voy a llevar a cabo nunca os traigo a estas líneas un paquete más que interesante de R que nos permite obtener datos de las estaciones meteorológicas de los aeropuertos del mundo (https://www.wunderground.com/history/airport/) y encima te lo pone como un objeto de R, qué más podemos pedir. En github tenéis una completa batería de ejemplos de uso. En el caso de que necesitemos descargar información meteorológica de España tenemos que irnos a http://weather.rap.ucar.edu/surface/stations.txt donde están listados todos los aeropuertos que recoge este sistema de información, buscamos SPAIN y nos interesa el "ICAO" que es el International Civil Aviation Organization, el código del aeropuerto vamos. Con estas premisas si quiero recoger las temperaturas de 2015 del aeropuerto de Albacete:

install.packages("weatherData")
library(weatherData)

anio = getWeatherForYear("LEAB",2015)

La información de los aeropuertos es bastante completa y están distribuidos por toda la geografía nacional además tenemos muchos datos a nuestra disposición y bien tabulados. Yo conozco más de uno que se está acordando de mi por no haber escrito sobre este paquete unos meses antes. Saludos.

Truco SAS. Como leer PC Axis con SAS

Estoy leyendo información del INE que tiene que terminar cargándose en SAS y estos datos están en formato PC Axis. Existen macros en SAS para generar datasets a partir de PC Axis pero la verdad es que no he llegado a entender muy bien como funcionan y tras varios errores la mejor opción que he encontrado es emplear R y el paquete pxR que han creado algunos miembros de la Comunidad de R-Hispano. Como realizo esta tarea es más que sencillo:

En R realizamos la importación del archivo *.px:

nacionalidad = read.px("ubicacion\\seccion_censal_nacionalidad.px")
nacionalidad = data.frame(nacionalidad)
write.csv( nacionalidad, file = "ubicacion\\nacionalidad.csv" )

Hemos generado un csv que importamos desde SAS:

proc import datafile="ubicacion\nacionalidad.csv"
     out=nacionalidades
     dbms=csv
     replace;
     getnames=yes;
run;

También quería aprovechar esta entrada para comentaros que es preferible usar los viejos csv para mover archivos entre R  y SAS que usar librerías como SASxport que generan ficheros "portables" de SAS, aunque los ficheros "portables" garantizan que se puedan leer con distintas versiones de SAS este paquete tarda mucho (demasiado) tiempo en crear los archivos. Y si alguien tiene una versión más sencilla de la macro de SAS que mande el link. Saludos.