我有一个数据帧,它存储了 4(或任何 N 个)变量的平均值和标准偏差
mean_sd_df <- data.frame(variable = c('x1', 'x2', 'x3', 'x4'),
mean_var = c(2, 3, 4, 8),
sd_var = c(0.2, 0.3, 0.4, 0.6))
我还有另一个数据帧,其中包含上述四个变量的值,需要使用上述数据框中的平均值和 sd 进行标准化
set.seed(123)
dat.mat <- data.frame(x1 = sample(1:10, 4),
x2 = sample(1:10, 4),
x3 = sample(1:10, 4),
x4 = sample(1:10, 4))
这就是我进行标准化的方式。
dat.mat[ , 1] <- (dat.mat[ , 1] - mean_sd_df[1, 'mean_var'])/mean_sd_df[1, 'sd_var']
dat.mat[ , 2] <- (dat.mat[ , 2] - mean_sd_df[2, 'mean_var'])/mean_sd_df[2, 'sd_var']
dat.mat[ , 3] <- (dat.mat[ , 3] - mean_sd_df[3, 'mean_var'])/mean_sd_df[3, 'sd_var']
dat.mat[ , 4] <- (dat.mat[ , 4] - mean_sd_df[4, 'mean_var'])/mean_sd_df[4, 'sd_var']
如果我有很多变量,这可能会变大,所以想知道是否有更简单的方法可以做到这一点?
您可以定义一个作用于列的函数,并使用lapply
在所有列上运行它:
standardize <- function(col, df, mean_sd_df){
ind_row <- which(mean_sd_df$variable == col)
df[[col]] <- (df[[col]] - mean_sd_df[ind_row, "mean_var"])/mean_sd_df[ind_row, "sd_var"]
return(df[[col]])
}
dat.mat <- as.data.frame(lapply(names(dat.mat), standardize,
df=dat.mat,
mean_sd_df=mean_sd_df),
col.names = names(dat.mat))
输出
x1 x2 x3 x4
1 5 10.000000 5.0 -5.000000
2 40 6.666667 12.5 -8.333333
3 0 3.333333 -5.0 1.666667
4 30 23.333333 -2.5 -11.666667
这是一个带有pivot_longer/pivot_wider
的选项。 使用pivot_longer
将数据重塑为"长"格式,left_join
使用"mean_sd_sf"数据集,使用pivot_wider
标准化并重新塑造回"宽"格式
library(dplyr)
library(tidyr)
dat.mat %>%
mutate(rn = row_number()) %>%
pivot_longer(cols = -rn) %>%
left_join(mean_sd_df, by = c('name' = 'variable')) %>%
transmute(rn, name, value = (value - mean_var)/sd_var) %>%
pivot_wider(names_from = name, values_from = value) %>%
select(-rn)
# A tibble: 4 x 4
# x1 x2 x3 x4
# <dbl> <dbl> <dbl> <dbl>
#1 5 10 5 -5
#2 40 6.67 12.5 -8.33
#3 0 3.33 -5 1.67
#4 30 23.3 -2.5 -11.7
或与Map
base R
dat.mat[] <- Map(function(x, y, z) (x - y)/z, dat.mat,
mean_sd_df$mean_var, mean_sd_df$sd_var)