Как сгруппировать / стандартизировать переменные в R?

9

Функции, с которыми я знаком, включают масштабирование из базы R, масштабирование из ARM.

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

Майкл Бишоп
источник
Попробуйте: aggregate (state.x77, список (Region = state.region, Cold = state.x77 [, "Frost"]> 130)), функция (x) ((x - среднее (x)) / sd (x) ))
suncoolsu

Ответы:

7

Вот возможное решение Plyr . Обратите внимание, что он опирается на базовую transform()функцию.

my.df <- data.frame(x=rnorm(100, mean=10), 
                    sex=sample(c("M","F"), 100, rep=T), 
                    group=gl(5, 20, labels=LETTERS[1:5]))
library(plyr)
ddply(my.df, c("sex", "group"), transform, x.std = scale(x))

(Мы можем проверить, работает ли он, как ожидалось, например, with(subset(my.df, sex=="F" & group=="A"), scale(x)))

В основном, 2-й аргумент описывает, как «разбить» данные, 3-й аргумент - какую функцию применять к каждому чанку. Выше добавит переменную x.stdк data.frame. Используйте, xесли вы хотите заменить исходную переменную на масштабированную.

хл
источник
7
group.center <- function(var,grp) {
    return(var-tapply(var,grp,mean,na.rm=T)[grp])
}
Thanassi
источник
3

Вот решение data.table . Это определенно быстрее, чем plyr (актуально только для больших наборов данных). Может быть, позже я сделаю пример dplyr.

# generate example data
raw.data <- data.frame( outcome = c(rnorm(500, 100, 15), rnorm(500, 110, 12)), 
                        group = c(rep("a", 500), rep("b", 500)))

library(data.table)
# convert dataframe to data.table
raw.data <- data.table(raw.data, key = "group")

# create group standardized outcome variable
raw.data[ , group_std_outcome := (outcome - mean(outcome, na.rm = TRUE)) /  
           sd(outcome, na.rm = TRUE), "group"]

(Да, я заново открыл вопрос, который задавал много лет назад, когда был R noob;)

Майкл Бишоп
источник
2

Вы можете использовать (среди прочего) tapplyдля этого ( plyrпакет содержит множество других опций, которые могут лучше подходить для вашей конкретной ситуации):

tapply(variabletoscale, list(groupvar1, groupvar2), scale)
Ник Саббе
источник
1
С двумя факторами, он не вернет data.frame. Вам нужно будет постобработать результат для этого.
ЧЛ
0

Этот ответ взят из белой книги Махмуда Араи. Он имеет удобный побочный эффект, заключающийся в маркировке центрированных результатов с префиксом «C»:

gcenter <- function(df1,group) {
        variables <- paste(
              rep("C", ncol(df1)),  colnames(df1), sep=".")
        copydf <- df1
        for (i in 1:ncol(df1)) {
              copydf[,i] <- df1[,i] - ave(df1[,i], group, FUN=mean)}
        colnames(copydf) <- variables
        return(cbind(df1,copydf))}
RegressForward
источник
0

Вот обновленная реализация, использующая dplyr из tidyverse .

library(tidyverse)

my.df <- data.frame(x=rnorm(100, mean=10), sex=sample(c("M","F"), 100, rep=T))
my.df <- group_by(my.df, sex) %>% mutate(x.sd = as.numeric(scale(x)))
Брайан Леви
источник