Как сохранить имена столбцов при динамической передаче столбцов фрейма данных в "агрегат"

С фреймом данных, как показано ниже

df1 <- data.frame(a=seq(1.1,9.9,1.1), b=seq(0.1,0.9,0.1),
                  c=rev(seq(10.1, 99.9, 11.1)))

Я хочу объединить столбцы b а также c от a

Так что я бы сделал что-то вроде этого

aggregate(cbind(b,c) ~ a, data = df1, mean)

Это сделало бы это. Однако я хочу обобщить без жестко закодированных имен столбцов, как в функции.

myAggFunction <- function (df, col_main, col_1, col_2){
    return (aggregate(cbind(df[,col1], df[,col2]) ~ df[,col_main], df, mean))
    }
myAggFunction(df, 1, 2, 3)

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

 df2[, 1]  V1   V2

Как получить имена столбцов в исходном фрейме данных в возвращенном фрейме данных?

1 ответ

Решение

Я буду предполагать общий случай, когда у вас есть несколько LHS (левые стороны), а также несколько RHS (правые стороны).


Использование метода data.frame

## S3 method for class 'data.frame'
aggregate(x, by, FUN, ..., simplify = TRUE, drop = TRUE)

Если вы передадите объект как именованный список, вы получите сохраненные имена. Так что не обращайтесь к вашему фрейму данных с [, ], но с [], Вы можете построить свою функцию как:

## `LHS` and `RHS` are vectors of column names or numbers giving column positions
fun1 <- function (df, LHS, RHS){
  ## call `aggregate.data.frame`
  aggregate.data.frame(df[LHS], df[RHS], mean)
  }

Все еще используете метод "формулы"?

## S3 method for class 'formula'
aggregate(formula, data, FUN, ...,
          subset, na.action = na.omit)

Это немного утомительно, но мы хотим построить хорошую формулу с помощью:

as.formula( paste(paste0("cbind(", toString(LHS), ")"),
                  paste(RHS, collapse = " + "), sep = " ~ ") )

Например:

LHS <- c("y1", "y2", "y3")
RHS <- c("x1", "x2")
as.formula( paste(paste0("cbind(", toString(LHS), ")"),
                  paste(RHS, collapse = " + "), sep = "~") )
# cbind(y1, y2, y3) ~ x1 + x2

Если вы кормите эту формулу aggregate, вы получите приличные имена столбцов.

Так что сконструируйте свою функцию так:

fun2 <- function (df, LHS, RHS){
  ## ideally, `LHS` and `RHS` should readily be vector of column names
  ## but specifying vector of numeric positions are allowed
  if (is.numeric(LHS)) LHS <- names(df)[LHS]
  if (is.numeric(RHS)) RHS <- names(df)[RHS]
  ## make a formula 
  form <- as.formula( paste(paste0("cbind(", toString(LHS), ")"),
                      paste(RHS, collapse = " + "), sep = "~") )
  ## call `aggregate.formula`
  stats:::aggregate.formula(form, df, mean)
  }

замечание

aggregate.data.frame самый лучший aggregate.formula это обертка и позвонит model.frame внутри, чтобы сначала построить фрейм данных.

Я даю метод "формулы" в качестве опции, потому что способ, которым я создаю формулу, полезен для lm, так далее.


Простой, воспроизводимый пример

set.seed(0)
dat <- data.frame(y1 = rnorm(10), y2 = rnorm(10),
                  x1 = gl(2,5, labels = letters[1:2]))

## "data.frame" method with `fun1`
fun1(dat, 1:2, 3)
#  x1          y1         y2
#1  a  0.79071819 -0.3543499
#2  b -0.07287026 -0.3706127

## "formula" method with `fun2`
fun2(dat, 1:2, 3)
#  x1          y1         y2
#1  a  0.79071819 -0.3543499
#2  b -0.07287026 -0.3706127

fun2(dat, c("y1", "y2"), "x1")
#  x1          y1         y2
#1  a  0.79071819 -0.3543499
#2  b -0.07287026 -0.3706127
Другие вопросы по тегам