В этой статье мы обсудим семейство функций apply () в R, их типы и некоторые из его типов, применяемых к различным структурам данных. Семейство apply () - это встроенный пакет в R, поэтому нам не нужно устанавливать его отдельно. Основное преимущество функции apply () заключается в том, что мы можем использовать эти функции в качестве альтернативы операциям цикла.

В этом посте мы узнаем, как мы можем использовать функцию R apply () и ее различные типы, такие как lapply (), sapply () , tapply (), mapply () и функция replicate (), применяемая к различным структурам данных. Итак, приступим!

Семейство apply () -

Семейство apply () предустановлено в базовом пакете R и состоит из различных функций для повторяющегося управления данными из массивов, списков, матриц и фреймов данных. Семейство функций apply () помогает нам выполнять операции с очень небольшим количеством строк кода. Эти функции могут быть -

  1. Векторизованные структуры, такие как списки, массивы, матрицы и т. Д.
  2. Агрегатная функция, такая как среднее значение, сумма, среднее значение и т. Д.

Как и когда мы должны их использовать?

Использование этих функций зависит от структуры данных, с которыми мы хотим работать, и формата вывода, который нам нужен. Давайте посмотрим, как выполнять эти функции одну за другой -

Функция apply ()

Начнем с первой функции семейства, функции apply (). Это работает с массивами. Для упрощения мы будем использовать в этом уроке только 2D-массивы. Во-первых, давайте посмотрим, как работает основная функция применения. Мы можем использовать раздел справки RStudio, чтобы получить описание этой функции.

?apply()

В документации R показан синтаксис функции следующим образом:

apply(X, MARGIN, FUN, ...)

Где:-

  1. X - это 2D-массив.
  2. MARGIN - это переменная, которая определяет, как мы можем применить функцию. Когда Margin = 1, оно применяется к строкам, а когда Margin = 2, оно применяется к столбцам, а когда Margin = c (1,2), оно применяется как к строкам, так и к столбцам.
  3. FUN - это функция, которую мы применяем к данным. Это может быть любая функция R, включая определяемую пользователем функцию (UDF).
  4. … .. это используется для любых других аргументов, передаваемых функции.

Давайте построим матрицу 4 x 4 и вычислим сумму значений каждого столбца:

matrix_1 <- matrix(1:16, nrow = 4)
matrix_1

Мы получим следующий результат -

[,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16

Давайте посчитаем сумму значений каждой строки -

apply(matrix_1, 1, sum)

Мы получим следующий результат -

[1] 28 32 36 40

Давайте посчитаем сумму значений каждого столбца -

apply(matrix_1, 2, sum)

Мы получим следующий результат:

[1] 10 26 42 58

Давайте введем значение NA в матрицу и посмотрим, как мы можем выполнить функцию -

matrix_1[2,3] <- NA
matrix_1

Мы получим следующий результат:

[,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   NA   14
[3,]    3    7   11   15
[4,]    4    8   12   16

Давайте использовать функцию применения -

apply(matrix_1, 1, sum)

Мы получим следующий результат -

[1] 28 NA 36 40

Передача аргумента na.rm в приведенный выше код -

apply(matrix_1, 1, sum, na.rm = TRUE)

Мы получим следующий результат -

[1] 28 22 36 40

Теперь давайте удалим это NA -

matrix_1[2,3] <- 10
matrix_1

Мы получим следующий результат -

[,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16

В приведенных выше примерах мы использовали функцию apply () для вычисления суммы строки или столбца. В приведенном ниже примере мы будем использовать функцию apply () для преобразования значений в каждой строке и столбце. Обратите внимание на аргумент MARGIN. Мы определим функцию для умножения каждого элемента матрицы на 5 и установим аргумент MARGIN равным 1: 2, чтобы функция могла работать с каждой строкой и столбцом матрицы.

matrix_2 <- apply(matrix_1,1:2, function(x) x*5)
matrix_2

Мы получим следующий результат:

[,1] [,2] [,3] [,4]
[1,]    5   25   45   65
[2,]   10   30   50   70
[3,]   15   35   55   75
[4,]   20   40   60   80

В предыдущих примерах мы использовали функцию apply () для матрицы. Но давайте посмотрим, что произойдет, если вместо этого мы перебираем вектор?

Давайте сначала создадим вектор -

vector_1 <- c(1:15)
vector_1

Мы получим следующий результат -

[1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15

Давайте использовать функцию apply () -

apply(vector_1, 1, sum)

Если вы запустите эту функцию, вы получите следующую ошибку -

Error in apply(vector_1, 1, sum) : dim(X) must have a positive length

Как видите, это не сработало, потому что функция apply () лучше всего работает только тогда, когда данные имеют как минимум два измерения. Если используемые данные находятся в векторном формате, тогда нам нужно вместо этого использовать другие функции, такие как lapply (), sapply () или vapply ().

Функция lapply ()

Мы используем эту функцию, когда хотим применить заданную функцию, которая будет перебирать каждый элемент данных в списке или векторе. Мы можем использовать раздел справки RStudio, чтобы получить описание этой функции.

?lapply

В документации R показан синтаксис функции следующим образом. Обратите внимание, что в этой функции нет аргумента MARGIN.

lapply(X, FUN, ....)

Мы можем использовать эту функцию для других объектов, таких как фреймы данных, списки или векторы, и результат, который мы получаем взамен, находится в форме списка (поэтому имя начинается с «l»), который имеет такое же количество элементов, как и объект передан ему. Мы создадим три матрицы с именами A, B и C и извлечем значения из столбца, чтобы увидеть, как это работает.

A = matrix(1:16, nrow = 4)
B = 1:10
C = 15:20
my_list <- list(A,B,C)
my_list

Мы получим следующий результат -

[[1]]
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16

[[2]]
[1]  1  2  3  4  5  6  7  8  9 10

[[3]]
[1] 15 16 17 18 19 20

Давайте посчитаем сумму каждого списка -

lapply(my_list, sum)

Мы получим следующий результат -

[[1]]
[1] 136

[[2]]
[1] 55

[[3]]
[1] 105

Мы видим, как результаты сохраняются в виде списка. Если мы хотим получить результат в векторной форме, мы должны передать аргумент unlist функции lapply () -

unlist(lapply(my_list, sum))

Мы получим следующий результат -

[1] 136  55 105

Мы также можем создать нашу собственную функцию и передать ее lapply (). Например, если мы хотим добавить 10 к каждому элементу, мы будем использовать код, как показано ниже -

lapply(my_list, function(x) x + 10)

Мы получим следующий результат -

[[1]]
     [,1] [,2] [,3] [,4]
[1,]   11   15   19   23
[2,]   12   16   20   24
[3,]   13   17   21   25
[4,]   14   18   22   26

[[2]]
[1] 11 12 13 14 15 16 17 18 19 20

[[3]]
[1] 25 26 27 28 29 30

Функция sapply ()

Функция sapply () работает так же, как функция lapply (), но пытается упростить вывод, если это возможно. И действительно, функция sapply () является функцией «оболочка» для lapply (). Мы можем использовать раздел справки RStudio, чтобы получить описание этой функции.

?sapply

В документации R показан синтаксис функции следующим образом. Обратите внимание, что в этой функции также нет аргумента MARGIN.

sapply(X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE)

Это означает, что вместо возврата списка, такого как lapply (), он будет возвращать вектор, если данные можно упростить. Для этого воспользуемся тем же примером my_list.

sapply(my_list, sum)

Мы получим следующий результат -

[1] 136  55 105

Теперь давайте передадим аргумент simpleify = FALSE в приведенный выше код и посмотрим, что произойдет -

sapply(my_list, sum, simplify = FALSE)

Мы получим следующий результат -

[[1]]
[1] 136

[[2]]
[1] 55

[[3]]
[1] 105

Здесь мы видим, что результат возвращается в виде списка, а не вектора. Как и функция apply (), мы также можем использовать функцию для преобразования данных. Вот как мы можем это сделать -

print(sapply(my_list, function(x) x + 5))

Мы получим следующий результат -

[[1]]
       [,1] [,2] [,3] [,4]
[1,]    6   10   14   18
[2,]    7   11   15   19
[3,]    8   12   16   20
[4,]    9   13   17   21

[[2]]
[1]  6  7  8  9 10 11 12 13 14 15

[[3]]
[1] 20 21 22 23 24 25

Функция vapply ()

Функция vapply () похожа на функцию sapply (), но требует от пользователей указания типа данных, которые они передают аргументам функции vapply (). Мы можем использовать раздел справки RStudio, чтобы получить описание этой функции.

?vapply

В документации R показан синтаксис функции следующим образом. Обратите внимание, что в этой функции также нет аргумента MARGIN.

vapply(X, FUN, FUN.VALUE, …, USE.NAMES = TRUE)

FUN.VALUE - это то место, где нам нужно указать тип данных, которые мы передаем. Если вы хотите, чтобы каждый элемент в списке возвращал одно числовое значение, мы используем аргумент как FUN.VALUE = integer (1). Здесь также следует помнить, что упрощение всегда выполняется в случае функции vapply (). Эта функция проверяет, что все значения FUN совместимы с FUN.VALUE, для которого они должны иметь одинаковую длину и тип.

vapply(my_list, sum, FUN.VALUE = integer(1))

Мы получим следующий результат -

[1] 136  55 105

Функция replicate ()

Эта функция часто используется с семейством функций apply (). Когда мы передаем вектору функцию replicate (), он реплицирует свои значения определенное количество раз. Мы можем использовать раздел справки RStudio, чтобы получить описание этой функции.

?replicate

В документации R показан синтаксис функции следующим образом. Обратите внимание, что в этой функции также нет аргумента MARGIN.

replicate(n, expr, simplify = "array")

Где -

  1. n - целое число, показывающее количество повторений.
  2. expr - это выражение, которое нужно многократно оценивать.

Давайте посмотрим на пример -

hist(replicate(100, mean(rexp(10))))

Мы получим следующий результат -

Функция mapply ()

«M» в функции mapply () означает «многомерное» применение. Это смоделировано после функции sapply (). Мы используем эту функцию для векторизации аргументов функции, которая обычно не принимает векторы в качестве аргументов. Мы можем применить эту функцию к нескольким спискам или нескольким векторным аргументам. Мы можем использовать раздел справки RStudio, чтобы получить описание этой функции.

?mapply

В документации R показан синтаксис функции следующим образом. Обратите внимание, что в этой функции также нет аргумента MARGIN.

mapply(FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)

Где -

  1. Веселье - это функция, которую нужно применить
  2. …. аргументы для векторизации
  3. MoreArgs - это список других аргументов функции FUN.
  4. УПРОЩИТЬ - логическая или символьная строка. Это пытается уменьшить результат до вектора, матрицы или многомерного массива.
  5. USE.NAMES используется, если это вектор символов, мы используем этот вектор символов в качестве имен.

Рассмотрим следующий пример. Предположим, мы хотим воспроизвести 1 4 раза, 2 3 раза, 3 2 раза и 4 1 раз.

mapply(rep, times = 1:4, x = 4:1)

Мы получим следующий результат -

[[1]]
[1] 4

[[2]]
[1] 3 3

[[3]]
[1] 2 2 2

[[4]]
[1] 1 1 1 1

Есть еще один способ сделать это -

mapply(rep, times = 1:4, MoreArgs = list(x = 25))

Мы получим следующий результат -

[[1]]
[1] 25

[[2]]
[1] 25 25

[[3]]
[1] 25 25 25

[[4]]
[1] 25 25 25 25

Мы получим результат в виде списка. Чтобы получить вывод в векторной форме, используйте следующий код -

unlist(mapply(rep, times = 1:4, x = 4:1))

Мы получим следующий результат -

[1] 4 3 3 2 2 2 1 1 1 1

Теперь давайте создадим функцию и передадим ей функцию mapply (). Предположим, у нас есть два вектора и мы хотим умножить их на 2 после сложения друг друга. Итак, давайте сначала создадим функцию и передадим ей аргументы.

x <- c(A = 10, B = 20, C = 30)
y <- c(J = 40, K = 50, L = 60)
addition <- function(u,v){
  (u+v)*2
}
mapply(addition, x, y)

Мы получим следующий результат -

A   B   C 
100 140 180

Функция tapply () -

Эта функция применяет функцию к каждой ячейке рваного массива, то есть к каждой (непустой) группе значений, заданных уникальной комбинацией уровней определенных факторов. Мы можем использовать раздел справки RStudio, чтобы получить описание этой функции.

?tapply

В документации R показан синтаксис функции следующим образом. Обратите внимание, что в этой функции также нет аргумента MARGIN.

tapply(X, INDEX, FUN = NULL, ..., default = NA, simplify = TRUE)

Давайте загрузим набор данных iris в R и воспользуемся функцией tapply () для этого набора данных iris. Загрузим набор данных -

datasets::iris
head(iris)

Мы получим следующий результат -

Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

Предположим, если мы хотим вычислить среднее значение длины чашелистики для всех видов -

tapply(iris$Sepal.Length, iris$Species, mean)

Мы получим следующий результат -

setosa versicolor  virginica 
5.006      5.936      6.588

Точно так же мы можем рассчитать среднюю длину чашелистника для трех типов видов, используя этот код -

tapply(iris$Sepal.Length, iris$Species, median)

Мы получим следующий результат -

setosa versicolor  virginica 
5.0        5.9        6.5

Заключение -

В этой статье мы узнали о семействе функций apply () в R. Если вам понравилась эта статья или у вас есть какие-либо предложения для меня, дайте мне знать, оставив комментарий ниже.

Спасибо!