2015-09-28

Cómo crear una matriz simétrica en R

Title

Problema

Partimos de la siguiente matriz/data frame y deseamos crear una matriz simétrica.

Datos

  V1 V2 V3 V4 V5
1  0  2  3  4  5
2  0  0  6  8 10
3  0  0  0 12 15
4  0  0  0  0 20
5  0  0  0  0  0
df <- structure(list(V1 = c(0L, 0L, 0L, 0L, 0L), V2 = c(2L, 0L, 0L, 
0L, 0L), V3 = c(3L, 6L, 0L, 0L, 0L), V4 = c(4L, 8L, 12L, 0L, 
0L), V5 = c(5L, 10L, 15L, 20L, 0L)), .Names = c("V1", "V2", "V3", 
"V4", "V5"), class = "data.frame", row.names = c("1", "2", "3", 
"4", "5"))

Soluciones

  • Sumando la matriz transpuesta
  • df + t(df)
  • Función lower.tri.
  • df[lower.tri(df)] <- t(df)[lower.tri(df)]
      V1 V2 V3 V4 V5
    1  0  2  3  4  5
    2  2  0  6  8 10
    3  3  6  0 12 15
    4  4  8 12  0 20
    5  5 10 15 20  0

    Asignamos a la parte inferior de una matriz triangular superior, los valores de la parte superior. Con lower.tri obtenemos el triángulo inferior. Le asignamos la parte superior que transponemos previamente la matriz —t(df)—, por eso volvemos a usar lower.tri . Pues si usáramos upper.tri el resultado no sería una matriz simétrica.

    df[lower.tri(df)] <- df[upper.tri(df)]
      V1 V2 V3 V4 V5
    1  0  2  3  4  5
    2  2  0  6  8 10
    3  3  8  0 12 15
    4  6 12 10  0 20
    5  4  5 15 20  0
    

Entradas relacionadas

Referencias

2015-09-26

Crear barras de datos usando el formato condicional en Excel

Title En Excel es muy sencillo crear un gráfico de barras usando el formato condicional, con barras dentro de las celdas.

Pasos

  1. Seleccionamos el rango de celdas
  2. En el grupo Estilos de la ficha Inicio, clic en Formato condicional y, a continuación, en Barras de datos.
  3. Ajustamos el texto de las celdas si fuera necesario. En nuestro caso con el color de fuente blanco y aumentando la sangría a 2. Bien abriendo el cuadro de diálogo Formato de celdas haciendo clic en Ctrl+1.

    O bien en la pestaña Inicio, en los grupos correspondientes: Fuente y en el grupo Alineación, clic en Aumentar sangría.
  4. Ordenamos el rango en orden descendente para ganar en claridad

Entradas relacionadas

2015-09-22

Cómo comparar dos data frames en R

Title

Problema

Queremos comparar dos data frames en R y comprobar si tienen las mismas filas o no. También deseamos saber las filas que son iguales y diferentes.

Datos

   Date Time   pH
1  10/8  600 3.85
2  10/9  800 4.05
3 10/10 1300 3.95
   Date Time   pH
1  10/8  600 3.85
2 10/12  900 4.05
3 10/10 1300 3.95
df1 <- read.table(text="Date    Time    pH
                  1   10/8    600     3.85
                  2   10/9    800     4.05
                  3   10/10   1300    3.95", 
                  head=TRUE)
df2 <- read.table(text="Date    Time    pH
                  1    10/8    600     3.85
                  2    10/12   900     4.05
                  3    10/10   1300    3.95", 
                  head=TRUE)

Soluciones

Si solamente deseamos saber si dos data frames son o no iguales, es tan sencillo como:

identical(df1, df2)
[1] FALSE

Para comparar fila a fila, disponemos de varias alternativas con diferentes paquetes. A efectos ilustrativos calculamos las filas en df1 que no se encuentran en df2. Para obtener las de df2 no presentes en df2, alterar el orden en el código.

  • Paquete compare
  • library(compare)
    compare(df1, df2)
    
    FALSE [FALSE, FALSE, TRUE]
    La salida de datos indica primero si el data frame es igual y entre corchetes si las filas son iguales (TRUE) o no (FALSE). Si queremos incluir los valores no disponibles (NAs), utilizamos la función addNA:

  • Paquete dplyr
  • library(dplyr)
    
    Filas diferentes presentes en el df1

    anti_join(df1, df2)
    
      Date Time   pH
    1 10/9  800 4.05
    Filas comunes

    semi_join(df1, df2)
    
       Date Time   pH
    1  10/8  600 3.85
    2 10/10 1300 3.95
  • Paquete sqldf
  • library(sqldf)
    
    Filas diferentes presentes en el df1

    sqldf('SELECT * FROM df1 EXCEPT SELECT * FROM df2')
    
      Date Time   pH
    1 10/9  800 4.05
    Filas comunes

    sqldf('SELECT * FROM df1 INTERSECT SELECT * FROM df2')
    
       Date Time   pH
    1  10/8  600 3.85
    2 10/10 1300 3.95

    Entradas relacionadas

    Referencias

    2015-09-17

    ¿Cómo crear en R diagramas de caja agrupando los valores de x en intervalos?

    Title

    Problema

    Deseamos crear diagramas de caja agrupando los valores del eje x en intervalos.

    Soluciones

    Datos

    Generamos unos datos aleatorios y una secuencia que emplearemos para crear los intervalos.

    set.seed(12)
    y <- rnorm(1000)
    x <- rnorm(1000)
    rng <- seq(-3, 3, 0.5)
    
  • Paquete base
  • boxplot(y ~ cut(x, breaks = rng),las=2)
    
    Si queremos incluir los valores no disponibles (NAs), utilizamos la función addNA:

    boxplot(y ~ addNA(cut(x, breaks = rng)), las = 2)
    
  • Paquete ggplot2
  • Creamos primero el data frame con los intervalos.

    library(ggplot2)
    df <- data.frame(x = cut(x, breaks = rng), y = y)
    ggplot(data = df, aes(x = x, y = y)) + geom_boxplot(aes(fill = x))
    

    Entradas relacionadas

    Referencias

    2015-09-15

    Múltiples funciones de agregación con aggregate en R

    Title

    Problema

    Partimos del siguiente data frame:

      Branch Loan_Amount TAT
    1      A         100 2.0
    2      A         120 4.0
    3      A         300 9.0
    4      B         150 1.5
    5      B         200 2.0
    
    Y deseamos el siguiente resultado. Se agrupar por Branch, se cuenta el Number_of_loans y se suman tanto Loan_Amount como TAT.

      Branch Number_of_loans Loan_Amount  TAT
    1      A               3         520 15.0
    2      B               2         350  3.5
    
    Datos

    df <- structure(list(Branch = structure(c(1L, 1L, 1L, 2L, 2L), .Label = c("A", 
    "B"), class = "factor"), Loan_Amount = c(100L, 120L, 300L, 150L, 
    200L), TAT = c(2, 4, 9, 1.5, 2)), .Names = c("Branch", "Loan_Amount", 
    "TAT"), class = "data.frame", row.names = c(NA, -5L))
    

    Opciones

  • Paquete base
  • df1 <- aggregate(.~ Branch, df, FUN = "sum")
    df2 <- setNames(aggregate(Loan_Amount~Branch, df, length)[2], c("Number_of_loans"))
    cbind(df1, df2)
    
      Branch Loan_Amount  TAT Number_of_loans
    1      A         520 15.0               3
    2      B         350  3.5               2
    
  • Paquete dplyr
  • library(dplyr)
    df %>% 
      group_by(Branch) %>% 
      summarise(Number_of_loans = n(),
                Loan_Amount = sum(Loan_Amount),
                TAT = sum(TAT))
    
    Source: local data frame [2 x 4]
    
      Branch Number_of_loans Loan_Amount   TAT
      (fctr)           (int)       (int) (dbl)
    1      A               3         520  15.0
    2      B               2         350   3.5
    
  • Paquete sqldf
  • library(sqldf)
    sqldf("SELECT Branch, 
                  COUNT(Loan_Amount) Number_of_loans, 
                  SUM(Loan_Amount) Loan_Amount, 
                  SUM(TAT) TAT 
          FROM df 
          GROUP BY Branch")
    
      Branch Number_of_loans Loan_Amount  TAT
    1      A               3         520 15.0
    2      B               2         350  3.5
    

    Entradas relacionadas

    Referencias

    2015-09-12

    Número de ocurrencias acumulado de una lista en Excel

    Title

    Problema

    Deseamos añadir una columna con el número de ocurrencias acumulado de una lista. En nuestro ejemplo, las ocurrencias acumuladas del nombre —name— de la columna A, calculadas en la columna D.

    Solución

    1. En la celda D2 introducimos la siguiente fórmula:
    2. =CONTAR.SI($A$2:A2;A2)
      

    3. Arrastramos el controlador de relleno o copiamos la fórmula en el rango deseado. En nuestro ejemplo de D3 a D11.

    Notas

    En el argumento rango la parte izquierda es una referencia absoluta $A$2 y la derecha relativa A2. En criterio, introducimos la celda como referencia relativa A2. Cuando copiamos la fórmula hacia abajo, el rango se autoexpande quedando anclado en la celda con la referencia absoluta $A2$, y contando el número de ocurrencias hasta dicha celda. Así, en la celda D11 tendremos:

    =CONTAR.SI($A$2:A11;A11)
    

    Si en lugar de empezar en 1 quisiéramos empezar a contar desde cero, simplemente restamos 1 a la fórmula inicial:

    =CONTAR.SI($A$2:A2;A2)-1
    

    Entradas relacionadas

    Referencias

    2015-09-07

    Comparar el tiempo de ejecución de expresiones en R con microbenchmark

    Title

    Problema

    Queremos evaluar el tiempo de ejecución de varias expresiones en R. Partimos del ejemplo de la entrada anterior, en la que seleccionábamos un porcentajes de filas de un data frame mediante diferentes métodos.

    Utilizamos el conjunto de datos ToothGrowth, que cuenta con 60 filas. Lo partiremos en dos, la primera con un 70% de las filas (42) y la segunda con un 30% (18 filas). Aunque en este ejemplo no es necesario, empleamos la función round, para que en el caso de que por ejemplo el número de filas sea 6,6 devuelva 7 filas en lugar de 6.

    Opciones

  • head y tail
  • head(ToothGrowth, round(nrow(ToothGrowth)*0.7))
    tail(ToothGrowth, round(nrow(ToothGrowth)*0.3))
    
  • Filtrando con índices
  • porcentaje = round(0.7*nrow(ToothGrowth))
    ToothGrowth[1:porcentaje,]
    ToothGrowth[-(1:porcentaje),]
    
  • Usando dplyr
  • porcentaje = round(0.7*nrow(ToothGrowth))
    library(dplyr)
    slice(ToothGrowth, 1:porcentaje)
    slice(ToothGrowth, -(1:porcentaje))

    Medición

    library(microbenchmark)
    library(ggplot2)
    porcentaje <-  round(0.7*nrow(ToothGrowth))
    rdo <- microbenchmark(
      opcion1 = head(ToothGrowth, round(nrow(ToothGrowth) * 0.7)),
      opcion2 = ToothGrowth[1:porcentaje,],
      opcion3 = slice(ToothGrowth, 1:porcentaje))
    
    Cargamos microbenchmark para la medición y ggplot2 para la representación gráfica. Separamos cada expresión que deseamos evaluar por una coma. Por defecto microbenchmark ejecuta cada expresión 100 veces (neval en el resultado). Para modificar el número de veces incluimos el argumento times.

    Resultado

    rdo
    
    Unit: microseconds
        expr     min       lq      mean    median       uq      max neval
     opcion1 134.933  147.156  203.3685  179.6675  225.867 1017.378   100
     opcion2  98.756  105.112  138.9135  116.3565  161.334  418.490   100
     opcion3 978.756 1026.912 1096.2901 1056.2450 1087.289 3765.912   100
    
    Los resultados incluyen 8 columnas. El mínimo (min), cuartil inferior (lq), media (mean) ,mediana (median), cuartil superior (uq), y máximo (max). Nos centraremos en la mediana, y en los cuartiles inferior y superior (lq y uq) para hacernos una idea de la variabilidad. En nuestro ejemplo vemos que la mejor opción en todos los parámetros y con menor variabilidad es la opción 2. También debemos prestar atención a la unidad de medida, antes de las columnas con los resultados, en nuestro ejemplo microsegundos.

    Gráfico

    Generamos un gráfico de tipo violín con los resultados de la medición.

    autoplot(rdo)
    

    Entradas relacionadas

    Referencias

    Nube de datos