Используйте функцию «Применить семейство» для создания нескольких столбцов фрейма данных, работая с несколькими другими столбцами. - PullRequest
3 голосов
/ 10 октября 2019

Я делаю некоторые манипуляции с данными, включая создание нескольких столбцов, работая с другими столбцами. Работать с использованием цикла for легко, но я застрял, используя функцию apply like для выполнения кодирования.

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

Пример: допустим, у меня есть простой фрейм данных (на самом деле у меня гораздо больше столбцов):

> df <- data.frame("x1" = 1:2, "x2" = 3:4, "y1"= 1:2, "y2"= 3:4)

> df

x1 x2 y1 y2

1  3  1  3

2  4  2  4

Я хотел создать две другие переменные с именами z1 и z2, так что z1 =(x1 + y1) / 3 и z2 = (x2 + y2) / 3

Используя для цикла, я могу сделать это легко.

x.var <- paste("x", 1:2, sep = '')

y.var <- paste("y", 1:2, sep = '')

z.var <- paste("z", 1:2, sep = '')

for (i in 1:2) {

  df[[z.var[i]]] <- (df[[x.var[i]]] + df[[y.var[i]]])/3

}

df

  x1 x2 y1 y2        z1       z2

1  1  3  1  3 0.6666667 2.000000

2  2  4  2  4 1.3333333 2.666667

Как это можно преобразовать для циклаиспользуя какой-нибудь компактный код, используя семейные функции apply?

Ответы [ 2 ]

1 голос
/ 10 октября 2019

Мы можем использовать mutate

library(dplyr)
df %>%
    mutate(z1 = (x1 + y1)/3, z2 = (x2 + y2)/3)

Или с transform из base R

df <- transform(df, z1 = (x1 + y1)/3, z2 = (x2 + y2)/3)
df
#    x1 x2 y1 y2        z1       z2
#1  1  3  1  3 0.6666667 2.000000
#2  2  4  2  4 1.3333333 2.666667
0 голосов
/ 10 октября 2019

Если у вас есть сотни столбцов, рассмотрите rowSums (аналогично apply(mat, margin=1, sum)). И, как указывают ?rowSums документы:

Эти функции эквивалентны использованию apply с FUN = mean или FUN = sum с соответствующими полями, но работают намного быстрее.

df$z1 <- (rowSums(df[grepl("1", names(df))])) /3

df$z2 <- (rowSums(df[grepl("2", names(df))])) /3

Кроме того, вы можете назначить несколько столбцов одновременно:

df[paste0("z", 1:2)] <- cbind((rowSums(df[grepl("1", names(df))])) / 3,
                              (rowSums(df[grepl("2", names(df))])) / 3)

Еще больше с sapply для построения матрицы:

df[paste0("z", 1:2)] <- sapply(1:2, function(i) rowSums(df[grepl(i, names(df))]) / 3)

df
#   x1 x2 y1 y2        z1       z2
# 1  1  3  1  3 0.6666667 2.000000
# 2  2  4  2  4 1.3333333 2.666667
...