Mostrando entradas con la etiqueta apply. Mostrar todas las entradas
Mostrando entradas con la etiqueta apply. Mostrar todas las entradas

2020-06-24

Aplying a function by row in R

Title

Problem

We want to apply a function to each row of a data frame. In our example, we'd like to calculate the min and median for each row of a data frame.

df <- structure(list(V1 = c(5L, 4L, 7L), V2 = c(8L, 9L, 3L), V3 = c(12L, 
5L, 9L)), .Names = c("V1", "V2", "V3"), class = "data.frame", row.names = c(NA, 
-3L))
 V1 V2 V3
1  5  8 12
2  4  9  5
3  7  3  9

Solution

  • dplyr
  • library(dplyr)
    # Using the pipe operator %>%
    df %>% 
      rowwise() %>% 
      mutate(min = min(V1, V2, V3), median = median(c(V1, V2, V3)))
    # Without %>%
    mutate(rowwise(df), min = min(V1, V2, V3), median = median(c(V1, V2, V3)))
    

    Source: local data frame [3 x 5]
    Groups: 
    
         V1    V2    V3   min median
      (int) (int) (int) (int)  (int)
    1     5     8    12     5      8
    2     4     9     5     4      5
    3     7     3     9     3      7
    
  • Base package
  • df$min <- apply(df, 1, min) df$median <- apply(df[, 1:3], 1, median)

      V1 V2 V3 min median
    1  5  8 12   5      8
    2  4  9  5   4      5
    3  7  3  9   3      7
    

    References

    2020-03-05

    Descriptive statistics by group in R

    Title

    Problem

    We'd like to report descriptive statistics in R by a grouping variable and subsetting the output statistics.

    Solution

    We will use the data frame iris, columns Sepal.Length and Sepal.Width and grouping by Species. In our example, we want to return the mean, the standard deviation, the skewness and kurtosis.

  • Subset of descriptive statistics by group
  • library(psych)
    # Variables by index
    d <- describeBy(iris[1:2], group = iris$Species)
    # Two options to subset the statistics:
    lapply(d, "[", , c(3, 4, 11, 12))
    lapply(d, subset, , c(3, 4, 11, 12)) 
    
    # Variables by name
    i <- match(c("Sepal.Length", "Petal.Length"), names(iris))
    d <- describeBy(iris[i], group = iris$Species)
    lapply(d, subset, , c("mean", "sd", "skew", "kurtosis")) 
    
    $setosa
                 mean   sd skew kurtosis
    Sepal.Length 5.01 0.35 0.11    -0.45
    Sepal.Width  3.43 0.38 0.04     0.60
    
    $versicolor
                 mean   sd  skew kurtosis
    Sepal.Length 5.94 0.52  0.10    -0.69
    Sepal.Width  2.77 0.31 -0.34    -0.55
    
    $virginica
                 mean   sd skew kurtosis
    Sepal.Length 6.59 0.64 0.11    -0.20
    Sepal.Width  2.97 0.32 0.34     0.38
    
  • Subset of descriptive statistics without grouping
  • # Seleccionamos las columnas deseadas de la tabla
    d <- describe(iris[1:2])
    # Subsetting output statistics
    d[, c(3, 4, 11, 12)]
    
                 mean   sd skew kurtosis
    Sepal.Length 5.84 0.83 0.31    -0.61
    Sepal.Width  3.06 0.44 0.31     0.14
    

    References

    2019-05-23

    How to apply a function across rows in R

    Problem

    We'd like to apply a function across rows in R. In our example, we will add two columns calculating the minimum and the median for each row.

    df <- structure(list(V1 = c(5L, 4L, 7L), V2 = c(8L, 9L, 3L), V3 = c(12L, 
    5L, 9L)), .Names = c("V1", "V2", "V3"), class = "data.frame", row.names = c(NA, 
    -3L))
    
     V1 V2 V3
    1  5  8 12
    2  4  9  5
    3  7  3  9
    

    Solution

  • dplyr
  • library(dplyr)
    # Using the piper operator %>%
    df %>% 
      rowwise() %>% 
      mutate(min= min(V1, V2, V3), median = median(c(V1, V2, V3)))
    # Without the pipe operator %>%
    mutate(rowwise(df), min = min(V1, V2, V3), median = median(c(V1, V2, V3)))
    

    Source: local data frame [3 x 5]
    Groups: 
    
         V1    V2    V3   min median
      (int) (int) (int) (int)  (int)
    1     5     8    12     5      8
    2     4     9     5     4      5
    3     7     3     9     3      7
    
  • Base R
  • df$min <- apply(df, 1, min) df$median <- apply(df[, 1:3], 1, median)

      V1 V2 V3 min median
    1  5  8 12   5      8
    2  4  9  5   4      5
    3  7  3  9   3      7
    

    Related posts

    References

    2016-05-28

    Filtrar filas de un data frame en función de múltiples condiciones en R

    Title

    Problema

    Queremos filtrar el siguiente data frame, conservando aquellas filas que contengan el valor 123 o 321.

      Index odx1 odx2 odx3 odx4 odx5
    1     1  123    0    0    0    0
    2     2    0  321    0    0    0
    3     3    0    0    0  123    0
    4     4    0  321    0    0    0
    5     5    0    0    0    0    0
    

  • Datos originales
  • df <- structure(list(Index = 1:5, odx1 = c(123L, 0L, 0L, 0L, 0L), odx2 = c(0L, 
    321L, 0L, 321L, 0L), odx3 = c(0L, 0L, 0L, 0L, 0L), odx4 = c(0L, 
    0L, 123L, 0L, 0L), odx5 = c(0L, 0L, 0L, 0L, 0L)), .Names = c("Index", 
    "odx1", "odx2", "odx3", "odx4", "odx5"), class = "data.frame", row.names = c(NA, 
    -5L))
    

    Solución

  • Paquete base
  • df[apply(df, 1, function(x) {any(x == 123| x == 321)}),]
    
  • Paquete dplyr
  • library(dplyr)
    filter(df, rowSums(mutate_each(df, funs(. %in% c(123, 321)))) >= 1L)
    
    Con mutate creamos una matriz de valores lógicos que evaluamos con rowSums.

    mutate_each(df, funs(. %in% c(123, 321)))
      Index odx1 odx2 odx3 odx4 odx5
    1     1  123    0    0    0    0
    2     2    0  321    0    0    0
    3     3    0    0    0  123    0
    4     4    0  321    0    0    0
    

    Referencias

    2016-03-12

    Calcular el mínimo y la mediana de cada fila en R

    Title

    Problema

    Queremos añadir al siguiente data frame dos columnas con el mínimo y la mediana de cada fila.

    df <- structure(list(V1 = c(5L, 4L, 7L), V2 = c(8L, 9L, 3L), V3 = c(12L, 
    5L, 9L)), .Names = c("V1", "V2", "V3"), class = "data.frame", row.names = c(NA, 
    -3L))
    
     V1 V2 V3
    1  5  8 12
    2  4  9  5
    3  7  3  9
    

    Solución

  • dplyr
  • library(dplyr)
    # Usando el operador %>%
    df %>% 
      rowwise() %>% 
      mutate(min= min(V1, V2, V3), median = median(c(V1, V2, V3)))
    # Sin el operador %>%
    mutate(rowwise(df), min = min(V1, V2, V3), median = median(c(V1, V2, V3)))
    

    Source: local data frame [3 x 5]
    Groups: 
    
         V1    V2    V3   min median
      (int) (int) (int) (int)  (int)
    1     5     8    12     5      8
    2     4     9     5     4      5
    3     7     3     9     3      7
    
  • Paquete base R
  • df$min <- apply(df, 1, min) df$median <- apply(df[, 1:3], 1, median)

      V1 V2 V3 min median
    1  5  8 12   5      8
    2  4  9  5   4      5
    3  7  3  9   3      7
    

    Entradas relacionadas

    Referencias

    2015-10-17

    Substraer a cada valor de una fila la mediana de su respectiva fila en R

    Title

    Problema

    Queremos substraer a cada valor de una fila la mediana de la fila.

    Datos

    Creamos una matriz de 5x10.

    set.seed(24)
    m1 <- matrix(sample(0:9, 10*5, replace=TRUE), ncol=5)
    
          [,1] [,2] [,3] [,4] [,5]
     [1,]    2    6    0    3    4
     [2,]    2    3    5    2    3
     [3,]    7    6    7    3    2
     [4,]    5    6    1    1    2
     [5,]    6    3    2    9    0
     [6,]    9    9    6    2    0
     [7,]    2    1    0    7    3
     [8,]    7    0    5    6    3
     [9,]    8    5    6    6    2
    [10,]    2    1    0    9    3

    Solución

    m1 - apply(m1, 1, median)
    
          [,1] [,2] [,3] [,4] [,5]
     [1,]   -1    3   -3    0    1
     [2,]   -1    0    2   -1    0
     [3,]    1    0    1   -3   -4
     [4,]    3    4   -1   -1    0
     [5,]    3    0   -1    6   -3
     [6,]    3    3    0   -4   -6
     [7,]    0   -1   -2    5    1
     [8,]    2   -5    0    1   -2
     [9,]    2   -1    0    0   -4
    [10,]    0   -1   -2    7    1
    Si queremos conocer la mediana de cada fila.

    apply(m1, 1, median)
    
    [1] 3 3 6 2 3 6 2 5 6 2
    

    Notas

    Empleamos la función apply para aplicar una función a cada fila, en este caso la función median (mediana). En el segundo argumento de la función 1 indica que la función será aplicada sobre las filas (fila a fila). Las funciones apply son muy útiles en R pues evitan el uso de bucles (loops), pudiendo aplicar funciones a los márgenes, filas o columnas, de una matriz.

    Entradas relacionadas

    Referencias

    2015-08-24

    Seleccionar sólo las columnas que contengan NA en R

    Title

    Problema

    De un data frame deseamos seleccionar aquellas columnas que contengan algún valor NA.

    i3 <- c(1, 1, 1, 1, 2, 2)
    i2 <- c(NA, 1, 1, 1, 2, 2)
    i1 <- c(1, NA, 2, 4, 5, 3)
    newdat1 <- data.frame(i3, i2, i1)
    newdat1
    
      i3 i2 i1
    1  1 NA  1
    2  1  1 NA
    3  1  1  2
    4  1  1  4
    5  2  2  5
    6  2  2  3
    

    Soluciones

    De mayor a menor eficiencia.

  • sapply
  • newdat1[, sapply(newdat1, anyNA), drop = FALSE]
    
      i2 i1
    1 NA  1
    2  1 NA
    3  1  2
    4  1  4
    5  2  5
    6  2  3
    
  • colSums
  • newdat1[,is.na(colSums(newdat1))]
    
  • complete.cases
  • Mi alternativa propuesta. Transponemos el data frame y con complete.cases obtenemos un índice lógico (TRUE, FALSE, FALSE) con las columnas tienen algún NA. Como son aquellas que deseamos con incluir, con el operador ! invertimos el vector lógico anterior (FALSE, TRUE, TRUE) quedándonos con la segunda y tercera columnas.

    newdat1[!complete.cases(t(newdat1))]
    
  • apply
  • apply(newdat1, 2, function(x) sum(is.na(x)) == 0 )
    

    Referencias

    Nube de datos