Обзор

  • Манипулирование данными - один из важнейших шагов в жизненном цикле машинного обучения.
  • Давайте научимся использовать наиболее широко используемый набор функций apply для преобразования данных в R

Вступление

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

Кроме того, именно здесь квалифицированный специалист по данным применяет свою интуицию и опыт, чтобы извлечь из данных как можно больше информации. Таким образом, неудивительно, что как в Python, так и в R существует множество функций и инструментов, которые помогут нам в решении этой задачи.

Сегодня мы будем использовать R и узнаем о наиболее широко используемом наборе функций «применить» для преобразования данных в R. Это семейство функций предлагает эффективные и быстрые операции с данными. Это особенно полезно, когда мы хотим работать только с определенными столбцами. Этот набор функций называется функциями apply (). Наряду с его вариантами, такими как sapply (), mapply () и т. Д., Нам предоставляется универсальный швейцарский армейский нож для манипулирования данными.

Если вы хотите сделать карьеру в области науки о данных и узнать об этих удивительных вещах, я рекомендую вам ознакомиться с нашей программой Certified AI & ML BlackBelt Accelerate.

Оглавление

Различный набор функций в этом семействе:

  • подать заявление
  • прихотливый
  • жизнерадостный
  • vapply
  • наносить
  • карта

Установка контекста

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

Так что запустите свои записные книжки или R-студию, и давайте приступим!

Нам не нужно устанавливать какие-либо другие библиотеки для использования функций apply. Итак, давайте начнем с создания простой матрицы числовых значений от 1 до 20, распределенных по 5 строкам и 4 столбцам:

data <- matrix(c(1:20), nrow = 5, ncol = 4) 
data

Так выглядит наша матрица. Теперь давайте начнем с функции apply ()

подать заявление()

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

?apply

Как мы видим, функция apply имеет структуру apply (X, MARGIN, FUN,…). Здесь,

  • X относится к набору данных (в нашем случае матрице), к которому мы будем применять операции
  • Параметры MARGIN позволяют нам указать, хотим ли мы применить операцию по строке или по столбцу (MARGIN = 1 для строк; MARGIN = 2 для столбцов)
  • FUN относится к любой пользовательской или встроенной функции, которую мы хотим «применить» к X

Давайте посмотрим на простой пример вычисления среднего значения каждой строки:

mean_rows <- apply(data, 1, mean) 
mean_rows

Это было довольно просто! Мы видим, как функцию apply () можно использовать для обобщения наших данных. В том же духе, давайте попробуем найти сумму e по каждому столбцу:

sum_cols <- apply(data, 2, sum)
sum_cols

Если мы хотим применить функцию ко всем элементам, мы просто напишем функцию apply следующим образом:

all_sqrt <- apply(data, 1:2, sqrt)
all_sqrt

Что, если мы хотим применить к данным пользовательскую функцию? Например, у меня есть функция, которая находит квадратный корень из (x - 1) для каждой строки:

fn = function(x) { return(sqrt(x - 1)) }

Затем мы применяем эту функцию к каждой строке:

apply(data, 1, fn)

До сих пор мы использовали функции, которые принимают только 1 параметр и применяли их к данным. Лучшее в семействе apply то, что они также работают с функциями, имеющими несколько аргументов! Давайте применим пользовательскую функцию, которая принимает 3 аргумента:

fn = function(x1, x2, x3) { return(x1^2 + x2 * x1 + x3) }

Мы берем x1 в качестве каждого значения из «data» и x2, x3 в качестве других аргументов, которые будут сначала объявлены, а затем переданы через функцию apply:

b = 2
c = 1 
# apply along each row:
row_fn <- apply(data, 1, fn, x2 = b, x3 = c)
# apply along each column:
col_fn <- apply(data, 2, fn, x2 = b, x3 = c)

Давайте проверим row_fn и col_fn

row_fn

col_fn

Остальная часть семейства apply () следует аналогичной структуре с аналогичными аргументами, за исключением нескольких изменений. Теперь давайте воспользуемся функцией lapply ().

lapply ()

Вышеупомянутая функция apply () имеет ограничение: данные должны быть матрицей не менее двух измерений, чтобы на них выполнялась функция apply (). Функция lapply () снимает это ограничение. Сокращенно от list-apply, вы можете использовать функцию lapply для списка или вектора. Будь то список векторов или простой вектор, lapply () можно использовать в обоих. Поскольку теперь мы имеем дело с векторами / списками, функция lapply также не нуждается в параметре MARGIN. При этом возвращаемый тип lapply также является списком.

В качестве основных параметров он принимает только данные и функцию:

лаппли (X, FUN)

Давайте посмотрим на несколько примеров:

# define a list
cart <- c("BREAD","BUTTER","MILK","COOKIES")

# use lapply to convert all to lower case
cart_lower <- lapply(cart, tolower)

#output
cart_lower

Теперь возьмем более сложный список списков:

data <- list(l1 = c(1, 2, 3, 4),
             l2 = c(5, 6, 7, 8),
             l3 = c(9, 10, 11, 12))

# apply the 'sum' function on data:
sum_list <- lapply(data, sum)

#output
sum_list

саппли ()

Функция sapply () (сокращение от simple-apply) похожа на функцию lapply. Единственное отличие заключается в типе возвращаемого результата - sapply () упрощает вывод на основе возвращаемых значений. Я создал простую таблицу, которая сообщает нам, какой тип возвращается:

Мы увидим примеры всех вышеперечисленных сценариев:

Сценарий 1: длина каждого элемента = 1

data <- list(l1 = c(1, 2, 3, 4))

# apply the 'sum' function on data:
sum_sapply1 <- sapply(data, sum)

#output
sum_sapply1

Используя lapply, чтобы увидеть разницу в выводах:

sum_lapply1 <- lapply(data, sum) sum_lapply1

Сценарий 2: Длина каждого элемента ›1 и то же

sum_lapply1 <- lapply(data, sum)
sum_lapply1

Какой результат дает lapply ()?

sum_lapply2 <- lapply(data, sum)
sum_lapply2

Сценарий 3. Длина каждого элемента ›1 и разная

data <- list(l1 = c(1, 2, 3),
l2 = c(5, 6, 7, 8),
l3 = c(9, 10))

# apply the 'sum' function on data:
sum_sapply3 <- sapply(data, sum)

#output
sum_sapply3

Сравним это с выводом lapply () на тех же данных:

sum_lapply3 <- lapply(data, sum) 
#output
sum_lapply3

vapply ()

Переходим к функции vapply (). Трио lapply (), apply () и vapply () специально адаптировано для векторов всех типов. В отличие от lapply () и sapply (), которые определяют тип данных вывода за нас, vapply () позволяет нам выбирать тип данных структуры вывода. Таким образом, параметры vapply ():

vapply (X, ВЕСЕЛЫЕ, ВЕСЕЛЫЕ.ЗНАЧЕНИЕ)

Здесь FUN.VALUE используется для указания типа данных, который вам нужен.

Это наиболее полезно, когда наш список / векторы содержат смесь чисел и строк:

data <- list(l1 = c(1, 2, 3, 4),
             l2 = c(5, 6, 7, 8),
             l3 = c(9, 10, 11, 12),
             l4 = c("a", "b", "c", "a"))

# apply the 'max' function on data:
sum_vapply <- vapply(data, max, numeric(1))

Как и ожидалось, мы получили ошибку, потому что невозможно вычислить максимальное значение из списка символов. Числовой (1) указывает, что мы хотим, чтобы на выходе были отдельные числовые значения, где длина каждого элемента равна 1. Что, если мы используем lapply () или sapply ()?

lapply(data, max)
sapply(data, max)

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

data <- list(l1 = c(1, 2, 3, 4),
             l2 = c(5, 6, 7, 8),
             l3 = c(9, 10, 11, 12),
             l4 = c("a", "b", "c", "a"))

# apply the 'max' function on data:
sum_vapply <- vapply(data, max, numeric(1))

Таким образом, всегда лучше использовать vapply (), когда вы работаете с фреймами данных, которые имеют разные типы данных функций.

tapply ()

Проще говоря, tapply () позволяет нам разделить данные на группы и выполнить операцию с каждой группой. Таким образом, когда вы предоставляете вектор в качестве входных данных, tapply () выполняет указанную операцию с каждым подмножеством вектора. Он принимает следующие параметры:

tapply (X, INDEX, FUN)

где ИНДЕКС представляет коэффициент, который вы хотите использовать для разделения данных. Звучит знакомо? Да, tapply () - это не что иное, как простой способ выполнить групповую операцию и применить некоторую функцию к этим сгруппированным данным!

Чтобы увидеть, как работает tapply (), давайте создадим 2 простых вектора

item_cat <- c("HOME", "SNACKS", "BEVERAGE", "STORAGE", "CLEANING", "STORAGE", "HOME", "BEVERAGE", "ELECTRONICS", "SNACKS")
item_qty <-c(25, 30, 45, 66, 15, 50, 35, 20, 15, 35)

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

tapply(item_qty, item_cat, mean)

Что делала функция tapply ()? Мы сгруппировали вектор item_qty по вектору item_cat, чтобы создать подмножества векторов. Затем мы вычисляем среднее значение каждого подмножества.

Использование tapply () упрощается тем, что он автоматически берет уникальные значения из вектора item_cat и практически мгновенно применяет нужную нам функцию к данным. Мы даже можем получить более одного значения для каждого подмножества:

tapply(item_qty, item_cat, function(x) c(mean(x), sum(x)))

Теперь мы подошли к последней функции в семействе функций apply () - функции mapply ().

mapply ()

mapply () означает многомерное применение и в основном является многомерной версией sapply (). Функция mapply лучше всего объясняется на примерах - поэтому давайте сначала воспользуемся ею, а затем попытаемся понять, как она работает.

Давайте сначала возьмем функцию, которая обычно не принимает 2 списка или 2 вектора в качестве аргументов - например, функцию max. Сначала возьмем 2 списка:

list1 <- list(a = c(1, 2, 3), b = c(4, 5, 6), c = c(7, 8, 9))
list2 <- list(a = c(10, 11, 12), b = c(13, 14, 15), c = c(16, 17, 18))

А что, если мы хотим найти максимальные значения между каждой парой элементов списков?

max(list1$a, list2$a)

Теперь эту функцию нельзя применять одновременно ко всем элементам list1 и list2. В таких случаях мы используем функцию mapply ():

mapply(function(num1, num2) max(c(num1, num2)), list1, list2)

Таким образом, функция mapply используется для выполнения функций с данными, которые обычно не принимают несколько списков / векторов в качестве аргументов. Это также полезно, когда вы хотите создать новые столбцы. Давайте сначала создадим фрейм данных из матрицы, которую мы определили изначально:

df <- as.data.frame(data)

Теперь мы создадим новую переменную, которая будет содержать произведение столбцов V1 и V3:

mapply(function(x, y) x/y, df$V1, df$V3)

Таким образом, мы видим, что mapply - действительно удобная функция при работе с фреймами данных.

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

iris_df<-datasets::iris head(iris_df)

Теперь мы можем вычислить среднее значение длины чашелистиков и ширины чашелистиков каждой строки с помощью функции apply ():

iris_df['Sepal_mean'] <- apply(iris_df[c("Sepal.Length", "Sepal.Width")], 1, mean)

Точно так же мы можем получить сводные значения каждого столбца для каждого вида во фрейме данных:

tapply(iris_df$Sepal.Width, iris_df$Species, mean)

Мы также можем создать новый столбец, показывающий сумму длины лепестка и ширины лепестка, используя функцию mapply ():

iris_df['Sum_Petal'] <- mapply(function(x, y) x+y, iris_df$Petal.Length, iris_df$Petal.Width)

Конечные заметки

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

Я рекомендую вам попробовать более сложные функции на более сложных наборах данных, чтобы полностью понять, насколько полезны эти функции. Как эти функции помогли вам в работе с наборами данных в R? Пожалуйста, поделитесь своими ответами и любыми вопросами ниже!

Вы также можете прочитать эту статью в нашем мобильном приложении.

Первоначально опубликовано на https://www.analyticsvidhya.com 11 февраля 2021 г.