2014-07-31

Enésimo valor más alto de una columna con SQL

Title Para seleccionar el enésimo valor más alto de una columna en Mc Access, creamos una consulta en vista SQL. En ella anidamos una consulta dentro de otra, mediante una subconsulta entre paréntesis. Este tipo de consulta no podemos crearla en vista diseño, necesitamos abrir la consulta en vista SQL y escribir el código.

SELECT TOP 1 *
FROM (SELECT TOP 2 * FROM Tabla ORDER BY Columna DESC) AS Tabla
ORDER BY Columna;
En primer lugar, la subconsulta ordena descendentemente tantas filas como el número de la fila que queremos obtener, 2 en el ejemplo. La fila objetivo será esa última. Finalmente, la consulta ordena ascendente el resultado y selecciona solamente la primera fila. Si en lugar del segundo valor más alto queremos el vigésimo, escribimos TOP 20 dentro de la subconsulta.

El problema del código anterior es que no excluye los duplicados del cálculo. Y devuelve tantas filas como duplicados de ese valor.

En la columna anterior devolvería incorrectamente el 144.000 como segundo valor más alto en lugar del 52.936.

Alternativa 1

Para sortear ese problema empleamos el siguiente código:

SELECT TOP 1 *
FROM (SELECT  TOP 2 * FROM (SELECT DISTINCT Columna FROM Tabla)
      ORDER BY Columna DESC)
ORDER BY Columna;
La estructura es idéntica al código anterior. En lugar de introducir la Tabla al inicio de la subconsulta, introducimos una subconsulta adicional con la función DISTINCT para listar los elementos no duplicados. De esta manera obtenemos el enésimo valor más alto correctamente excluyendo los duplicados.

Alternativa 2

Otra opción en el caso de que busquemos el segundo valor más alto:

SELECT Max(Columna) AS Segundo_valor
FROM Tabla
WHERE ((Columna)<(SELECT MAX(Columna)
                 FROM Tabla));
Selecciona el valor máximo de la columna de aquellas filas donde el valor de la misma sea menor que el máximo valor de la columna. Es decir el segundo valor más alto. El inconveniente respecto a la consulta anterior es que no nos permite localizar el enésimo valor más alto, solamente el segundo.

Referencias:
Stackoverflow

2014-07-28

Obtener los valores RGB y HSL en Excel sin VBA

Title En Excel podemos obtener los valores RGB (rojo, verde, azul) o HSL (matiz, saturación, luminosidad) sin necesidad de VBA. Es útil en el caso de que necesitemos obtener exactamente el mismo color en otras aplicaciones o lenguajes y viceversa. P.ej.: R, HTML, Photoshop, etc.

Celda y formas

1. Selecciona la celda o forma.

2. En la ficha Inicio, en el grupo Fuente, clic en la flecha junto a control de relleno y clic en Más colores.

3. Selecciona la pestaña Personalizado. En la parte inferior puedes seleccionar el modelo de color (RGB o HSL) y ver los valores correspondientes.

Al contrario que RGB, no podemos utilizar los valores HSL en VBA.

Gráficos

En el caso de color de relleno de gráficos. 1. Selecciona el elemento del gráfico. Se mostrarán las Herramientas de gráficos con las fichas Diseño, Presentación y Formato.

2. En la ficha Formato, clic en relleno de forma y clic en Más colores de relleno. Más colores.

3. Selecciona la pestaña Personalizado. En la parte inferior puedes seleccionar el modelo de color (RGB o HSL) y ver los valores correspondientes.

Entradas relacionadas:
Propiedades ColorIndex en VBA

2014-07-25

Cargar paquetes automáticamente al inicializar R

Title Al inicializar R, se cargan los siguientes paquetes por defecto: datasets, utils, grDevices, graphics, stats, methods. Cuando necesitamos cargar otro paquete o bien lo cargamos en la consola con las funciones library o require, o bien en nuestro R Script especificamos al comienzo los paquetes necesarios.

Si utilizamos muy frecuentemente algunos paquetes, quizá queramos cargarlos al inicializar R. El fichero Rprofile permite configurar o personalizar tu sesión en R cada vez que abrimos R. En este caso cargando los paquetes que deseemos al inicializar R.

1. En la consola de R tecleamos: file.edit(".Rprofile")
2. Abrirá el fichero .Rprofile si ya existe en tu directorio de trabajo o creará uno nuevo.
3. Especificamos los paquetes en la primera línea:

pkgs <- c("plyr", "reshape2", "psych")
options(defaultPackages = pkgs) 
rm(pkgs)
4. Guardamos el fichero .Rprofile y cada vez que abramos R buscará el .Rprofile y cargará los paquetes especificados en él.

Referencias

2014-07-21

Muestra aleatoria en Excel

Title Tenemos una lista de datos de los que queremos extraer una muestra aleatoria de valores. Partimos de la misma idea de una entrada anterior. Creamos una columna auxiliar con números aleatorios y, basándonos en el orden de esa columna, extraeremos n valores de la misma. Si hay duplicados aparecerán también en la muestra.

En la columna A tenemos la lista con los datos originales y en B la columna auxiliar con números aleatorios. En las columnas C y D la lista ordenada aleatoriamente, según la columna B, de dos maneras.

Fórmulas

'Columna C
=INDICE($A$3:$A$10;COINCIDIR(K.ESIMO.MAYOR($B$3:$B$10;FILA(A1));$B$3:$B$10;))
'Columna D
=INDICE($A$3:$A$10;JERARQUIA(B3;$B$3:$B$10))
La segunda función es más clara y sencilla. Presenta la desventaja de que JERARQUIA se ha reemplazado en Excel 2010 y puede que en el futuro no sea compatible con nuevas versiones de Excel.

Usando nombres

=INDICE(lista;COINCIDIR(K.ESIMO.MAYOR(aleatorios;FILA(A1));aleatorios;))
=INDICE(lista;JERARQUIA(B3;aleatorios))
Facilitan la lectura y el mantenimiento de la fórmula. Para los nombres lista y aleatorios sean dinámicos visita esta entrada.

Entradas relacionadas

  • Consulta para generar una muestra aleatoria en Ms Access
  • 2014-07-18

    Seleccionar la enésima fila de una tabla en Ms Access

    Title Para seleccionar la enésima fila de una tabla en Mc Access, creamos una consulta en Vista SQL. En ella anidamos una consulta dentro de otra, mediante una subconsulta entre paréntesis. Este tipo de consulta no podemos crearla en Vista diseño, necesitamos abrir la consulta en Vista SQL y escribir el código. En el ejemplo seleccionamos la fila 7791.

    SELECT TOP 1 *
    FROM (SELECT TOP 7791 * FROM Tabla ORDER BY CampoId) AS Tabla
    ORDER BY CampoId DESC;
    
    Argumentos:

    FROM (SELECT TOP, el número de la enésima fila
    FROM, nombre de la tabla
    ORDER BY, CampoId, campo autonumérico, identificador de la tabla
    AS, alias de la tabla

    Explicación

    En primer lugar, la subconsulta ordena ascendentemente tantas filas como el número de la fila que queremos seleccionar, 7791 en el ejemplo. La fila objetivo será esa última. Finalmente, la consulta ordena descendentemente el resultado y selecciona solamente la primera fila.

    Si nuestra tabla no tiene un campo autonumérico necesitamos crearlo:

    Clic con el botón secundario en la tabla y, a continuación, clic en Vista Diseño.
    En la Vista Diseño de la tabla, agregamos un campo Autonumérico y guardamos la tabla.
    Cerramos la ventana de la Vista Diseño.

    Empleamos el método anterior pues Jet SQL en Ms Access no admite ROW_NUMBER, OFFSET o LIMIT.

    2014-07-15

    Pegar texto sin formato en Ms Word

    Title En Word, para pegar texto sin formato:

    1. Abrimos el menú Pegado especial: Ctrl+Alt+G o en la ficha Inicio en el grupo Portapapeles clic en la flecha del botón Pegar y selecciona Pegado especial.

    2. Seleccionamos Texto sin formato.

    Crear método abreviado de teclado

    Cuando tenemos que repetir el proceso, éste resulta tedioso y poco eficiente. Nos fuerza, aunque trabajemos con atajos como Ctrl+C y Ctrl+V, a tener que usar el ratón. Una alternativa, es agilizar el proceso creando un atajo (método abreviado de teclado) asignado a una macro.

    1. Abrimos Word y, a continuación, el editor de Visual Basic con Alt+F11. O en la ficha Programador, en el grupo Código, clic sobre Visual Basic.

    2. Pega el siguiente código en un módulo de Normal.dotm.

    Sub Pegar()     
        Selection.PasteSpecial Link:=False, DataType:=wdPasteText
    End Sub
    

    3. Asignamos una combinación de teclas a la macro creada. Botón de inicio, Opciones de Word, clic en Personalizar o presionamos la secuencia ALT+A+O.

    4. En la parte inferior junto a Métodos abreviados de teclado, clic en Personalizar.

    a. En el Categorías cuadro de diálogo, clic en Macros.

    b. En el Macros cuadro de diálogo, clic en la macro creada anteriormente: Pegar.

    c. En el Nueva tecla de método abreviado cuadro, presionamos las teclas de método abreviado que desea asignar a la macro. En nuestro caso Ctrl + Mayús + V.

    d. Clic en Asignar.

    e. Clic en Cerrar para cerrar el cuadro de diálogo Personalizar el teclado.

    5. Clic en Aceptar para cerrar el cuadro de diálogo Opciones de Word.

    Referencias:
    Personalizar métodos abreviados de teclado

    2014-07-12

    Cambiar programáticamente la ruta de tablas vinculadas en Access

    Title Al cambiar las bases de datos de carpeta o de unidad es posible que se rompa la ruta de las tablas vinculadas. Desafortunadamente Ms Access no permite establecer rutas con referencias relativas para las tablas vinculadas. En el caso de que tengamos que cambiar la ruta, lo podemos hacer manualmente o mediante código.

    Manualmente

    1. Clic con el botón secundario sobre la tabla vinculada, seleccionamos Administrador de tablas vinculadas.
    2. Activamos la casilla de verificación Preguntar siempre por la nueva ubicación.
    3. Marcamos la casilla de verificación de las tablas que deseamos cambiar y clic en Aceptar.
    4. Seleccionamos en el cuadro de diálogo la nueva base de datos y clic en Abrir.

    Programáticamente

    En el primer ejemplo, tenemos solamente una tabla vinculada a una base de datos en la misma carpeta que el fichero de Access actual. Es necesario escribir tanto el nombre de la tabla vinculada como el de la base de datos origen de la misma.

    Sub CambiarRutaTablaVinculada()
        Dim dbs As DAO.Database
        Set dbs = CurrentDb 
        dbs.TableDefs("Tabla vinculada").Connect = ";DATABASE=" _
            & CurrentProject.Path & "\BBDD de la tabla vinculada.mdb"
        dbs.TableDefs("Tabla Vinculada").RefreshLink 
    End Sub
    End Sub
    
    En este segundo ejemplo, se actualizan todas las tablas vinculadas. Se asume que las bases de datos origen de las mismas están en la misma carpeta que el fichero de Access actual.

    Sub CambiarTodasRutasTablaVinculadas()
        Dim fso As New FileSystemObject
        Dim fileName As String
        Dim dbs As DAO.Database
        Dim tdf As DAO.TableDef
        Set dbs = CurrentDb
        For Each tdf In dbs.TableDefs
        fileName = fso.GetFileName(tdf.Connect)
            If fileName <> "" Then
                dbs.TableDefs(tdf.Name).Connect = ";DATABASE=" _
                    & CurrentProject.Path & "\" & fileName
                dbs.TableDefs(tdf.Name).RefreshLink
            Else
            End If
        Next tdf
    End Sub
    

    2014-07-09

    Múltiples valores y funciones de agregación con reshape2 y plyr

    Title Anteriormente tratamos de la agregación de datos con reshape2. En esta ocasión examinaremos dos aspectos: la creación de múltiples variables de medida y de varias funciones de agregación al agrupar los datos.

    Puedes descargar el fichero Análisis de ventas2.csv y copiarlo en tu directorio de trabajo. He añadido la columna margen que utilizaremos junto con las ventas y eliminado los separadores de miles de las ventas.

    Múltiples variables de medida

    1. Importamos nuestros datos

    require(plyr)  # Para usar la función . de plyr
    require(reshape2)
    data <- read.csv("Análisis de ventas2.csv", sep = ";") # O bien
    data <- read.csv2("Análisis de ventas2.csv")
    
    2. Formateamos los datos importados.

    names(data) <- tolower(names(data))  # Nombres de columnas en minúsculas
    data$ventas <- sub(",", ".", data$ventas)  # Separador decimal el punto
    data$ventas <- as.numeric(data$ventas)  # Ventas tipo de variable numérica
    data$margen <- sub(",", ".", data$margen)  # Separador decimal el punto
    data$margen <- as.numeric(data$margen)  # Margen tipo de variable numérica
    data$fecha.de.pedido <- as.Date(data$fecha.de.pedido, "%d/%m/%Y") # Fechas
    
    3. Definimos identifiers (id.vars) y measured variables (measure.vars) con melt. Identificadores o nombres de columna y variables de medida o valores. Para añadir más variables, las especificamos en el argumento measure.vars.

    # Por posición, nº de columna.
    data.m <- melt(data, id.vars = c(1:20), measure.vars = c(6, 20))
    # Por nombre
    data.m <- melt(data, id.vars = c(1:20), measure.vars = c("ventas", "margen")) 
    
    A la derecha de la última id.vars (mesdetrimestre en este caso) crea dos columnas, con los nombres variable y value. Bajo variable incluirá aquellas definidas como measure.vars: las ventas y el margen. Bajo value, su valor correspondiente.
    4. Comenzamos a agregar datos usando dcast.

    # Por empleado ventas y margen. Función de agregación: sum.
    data.c <- dcast(data.m, empleado ~ variable, sum, margins = "empleado")
    data.c # Resultado:
    
                   empleado   ventas   margen
    1      Francisco Chaves 19974.25 12614.81
    2      Humberto Acevedo  3786.50  3041.46
    3         Jesús Escolar  2617.50  1629.45
    4     Juan Carlos Rivas  6378.00  3862.80
    5          Luis Bonifaz   680.00   571.20
    6        María González  6561.00  4548.92
    7    María Jesús Cuesta  6278.00  4518.62
    8 Pilar Pinilla Gallego  5787.50  3919.55
    9                 (all) 52062.75 34706.81
    
    Más ejemplos:

    Para cada agrupación dcast devolverá una columna por cada una de las variables (measure.vars) creadas, como en la tabla anterior. Para que sume ambas variables usamos "~ ." en lugar de "~ variable". A modo ilustrativo sumamos ventas y margen.

    # Por empleado suma de ventas y margen
    data.c <- dcast(data.m, empleado ~ ., sum, margins = "empleado")
    
                  empleado        .
    1      Francisco Chaves 32589.06
    2      Humberto Acevedo  6827.96
    3         Jesús Escolar  4246.95
    4     Juan Carlos Rivas 10240.80
    5          Luis Bonifaz  1251.20
    6        María González 11109.92
    7    María Jesús Cuesta 10796.62
    8 Pilar Pinilla Gallego  9707.05
    9                 (all) 86769.56
    
    # Total de ventas y margen separados
    data.c <- dcast(data.m, . ~ variable, sum) 
    
      .   ventas   margen
    1 . 52062.75 34706.81
    
    # Total de ventas y margen sumados
    data.c <- dcast(data.m, . ~ ., sum) 
    
      .        .
    1 . 86769.56
    
    Otras funciones de agregación, usando el ejemplo anterior:

    # Media
    data.c <- dcast(data.m, empleado ~ variable, mean, margins = "empleado")
    # Contar número de ocurrencias
    data.c <- dcast(data.m, empleado ~ variable, length, margins = "empleado")
    
    Mínimo y máximo generan un error. Es necesario usar la función suppressWarnings.

    Warning message:
    In .fun(.value[0], ...) : no non-missing arguments to min; returning Inf
    
    # Mínimo
    data.c <- suppressWarnings(dcast(data.m, empleado ~ variable, min, margins = "nombre.del.cliente"))
    # Máximo
    data.c <- suppressWarnings(dcast(data.m, empleado ~ variable, max, margins = "nombre.del.cliente"))
    

    Múltiples funciones de agregación

    Ahora explicamos cómo usar varias funciones de agregación al mismo tiempo. En la entrada y apartados anteriores usábamos solamente una función en cada agregación.

    1. Seguimos los pasos 1, 2 y 3 del punto anterior.

    2. Empleamos la función ddply del paquete plyr para presentar varias funciones de agregación en la misma tabla. En nuestro ejemplo, mínimo, media, máximo y desviación típica.

    resumen <- ddply(data.m, .(mes, empleado), summarise, min = min(value),
                                                         mean = mean(value),
                                                          max = max(value),
                                                           sd = sd(value))
    head(resumen)
    
      mes              empleado     min      mean  max        sd
    1   1      Francisco Chaves   68.25  620.8125 1400 648.62686
    2   1     Juan Carlos Rivas  231.84  253.9200  276  31.22584
    3   1    María Jesús Cuesta  175.50  490.8750  920 338.56126
    4   1 Pilar Pinilla Gallego   29.40  254.2000  530 199.75753
    5   2      Francisco Chaves  139.84  161.9200  184  31.22584
    6   2    María Jesús Cuesta 1621.20 1775.6000 1930 218.35457
    
    Los resultados consideran conjuntamente ventas y margen, se agrupan como si fueran una única variable. Para separar nuestras variables, en el argumento variables de la función ddply, especificamos mes, empleado y variable:

    resumen <- ddply(data.m, .(mes, empleado, variable), summarise,
                                                  min = min(value),
                                                mean = mean(value),
                                                  max = max(value),
                                                     sd = sd(value))
    head(resumen)
    
      mes           empleado variable    min    mean     max       sd
    1   1   Francisco Chaves   ventas 105.00 752.500 1400.00 915.7033
    2   1   Francisco Chaves   margen  68.25 489.125  910.00 595.2071
    3   1  Juan Carlos Rivas   ventas 276.00 276.000  276.00       NA
    4   1  Juan Carlos Rivas   margen 231.84 231.840  231.84       NA
    5   1 María Jesús Cuesta   ventas 270.00 595.000  920.00 459.6194
    6   1 María Jesús Cuesta   margen 175.50 386.750  598.00 298.7526
    
    Se puede observar como separa correctamente por fila los resultados por ventas y margen.

    ddply frente a dcast

    Compara la concisión con ddply frente a dcast. Además, ddply resume los datos en un único data.frame.

    resumen <- ddply(data.m, .(empleado, variable), summarise,
                                                  min = min(value),
                                                mean = mean(value),
                                                  max = max(value),
                                                    sd = sd(value),
                                            length = length(value))
    
    data.min <- suppressWarnings(dcast(data.m, empleado ~ variable, min, margins = "empleado"))
    data.mean <- dcast(data.m, empleado ~ variable, mean, margins = "empleado")
    data.max <- suppressWarnings(dcast(data.m, empleado ~ variable, max, margins = "empleado"))
    data.sd <- dcast(data.m, empleado ~ variable, sd, margins = "empleado")
    data.length <- dcast(data.m, empleado ~ variable, length, margins = "empleado")
    
    Referencias:
    Stackoverflow

    Entradas relacionadas:
    Agregar datos en R con el paquete reshape2

    2014-07-06

    Gráfico en cascada para valores negativos

    Title En la entrada anterior vimos como crear un gráfico en cascada usando una columna apilada. Sin embargo, si tenemos valores negativos necesitaríamos añadir dos series adicionales, diferenciando las subidas y bajadas por encima o por debajo del eje de abscisas.

    Otra forma más sencilla es usando barras ascendentes y descendentes.

    Datos

    Creamos tres columnas para las tres series del gráfico. La serie de inicio y final con el hueco para las variaciones. Dos series, antes y después, que son la serie original en el periodo anterior (antes) y en el periodo actual (después). Estas dos series nos permitirán mostrar las barras ascendentes y descendentes como diferencia entre ellas.

    Gráfico

    1. Representamos las tres series. La inicial y final como columna, y antes y después como líneas.

    2. En Herramientas de gráfico, en la ficha Presentación, hacemos clic sobre Barras ascendentes o descendentes y en Mostrar...

    3. Obtendremos el siguiente resultado

    4. Formateamos el gráfico. En formato de las dos líneas establecemos el color de línea en sin línea. Eliminamos los bordes de las barras y aplicamos el color de relleno correspondiente. Añadimos las etiquetas de los valores inicial, final y las variaciones. Formateamos las etiquetas del eje de abscisas.

    Entradas relacionadas

    Referencias

    2014-07-03

    Gráfico en cascada (waterfall chart) en Excel

    Title Un gráfico en cascada es un tipo de gráfico normalmente usado para comprender como un valor inicial se ve afectado por una serie de cambios intermedios positivos y negativos. Al parecer, este tipo de gráficos fueron popularizados por Mc Kinsey & company en sus presentaciones a clientes. Los valores iniciales y finales se representan con columnas enteras, mientras que los valores intermedios se componen de columnas flotantes. Estas columnas intermedias se formatean para distinguir los valores positivos y negativos.

    Gráfico

    Datos

    El gráfico anterior está compuesto de 4 series en una columna apilada que parten de una serie original.
    La primera serie es inicio y final, cuyos valores centrales están vacíos para dejar el hueco a las otras tres series auxiliares apiladas: intermediao, subidas y bajadas. La columna intermedio (auxiliar invisible) se calcula restando al valor anterior de la serie original la bajada de ese periodo.

    Día 1= 10.000 (Serie original) - 0 (Bajadas) Día 2= 12.000 (Serie original) - 3.000 (Bajadas)

    Restamos solo las bajadas pues las subidas se apilaran siempre sobre el valor intermedio íntegro anterior sin incluir la bajada. Las columnas subidas y bajadas calculan en valor absoluto la diferencia entre el valor actual y el anterior de la serie original. Las separamos en subidas y bajadas para diferenciarlas y poder aplicarles un formato diferente.

    Formato

    Creamos el gráfico, lo formateamos apropiadamente y añadimos etiquetas con los valores inicial y final y las variaciones.

    Entradas relacionadas

    Nube de datos