我有一个表示测试集T的数据框,另一个表示训练集D的数据框。这两个数据集中的列与从同一数据框中提取的列完全相同。
我使用以下代码对训练集D进行归一化
MaxMinNormalize <- function(num) {
if (is.factor(num)) num
else ((num - min(num)) / (max(num) - min(num)))
}
D_n <- as.data.frame(lapply(D, MaxMinNormalize))
数据中的某些列是因子,另一些是数字,这就是归一化功能的原因。
我想将此归一化步骤应用于测试集T,min
并max
从训练集中的各个列(而不是测试集中)获取和值。我应该怎么做呢?
感谢您的指导!
编辑:按照@coffeinjunky的指示,尝试了以下代码来测试使用混合类型的列(数字和因子)的能力:
df <- mtcars[,c("mpg", "cyl", "am", "gear")]
df$am <- as.factor(df$am)
df$gear <- as.factor(df$gear)
df1 <- df[1:16,]
df2 <- df[17:32,]
summary(df1)
summary(df2)
new_df <- data.frame(sapply(names(df1), function(col) {
ifelse(is.factor(df2[[col]]),
df2[[col]],
(df2[[col]]-min(df1[[col]]))/(max(df1[[col]])-min(df1[[col]])))
}))
head(new_df)
summary(new_df)
但是结果却很奇怪:函数也以某种方式存储在数据框中,并且列的名称丢失了。
> head(new_df)
sapply.names.df1...function.col...
mpg 0.3071429
cyl 1.0000000
am 1.0000000
gear 1.0000000
> summary(new_df)
sapply.names.df1...function.col...
Min. :0.3071
1st Qu.:0.8268
Median :1.0000
Mean :0.8268
3rd Qu.:1.0000
Max. :1.0000
我怀疑ifelse
处理因子列破坏了数据的结构。
可能最简单的方法是使用预先存在的功能,因为这是最方便的。例如,在这里,我们可以使用插入符号包中提供的功能。
为了说明,让我们获取一些玩具数据:
# get some test data:
df <- mtcars[,c("mpg", "cyl")]
df1 <- df[1:16,] # training data
df2 <- df[17:32,] # test data to be scaled
让我们看一下我们所期望的。
summary(df1) # some output ommitted
mpg cyl
Min. :10.4 Min. :4.0
Max. :24.4 Max. :8.0
summary(df2)
mpg cyl
Min. :13.30 Min. :4.000
Max. :33.90 Max. :8.000
我们看到for的范围(max - min
)是14,而for的范围是4。如果查看for的最大值,则for的范围是33.9 。将min减去10.4,再除以14,应得到23.5 / 14 = 1.6785。其他列和值也具有类似的数学公式。df1
mpg
cyl
df2
mpg
df1
现在,让我们使用caret::preProcess
并查看是否获得相同的值。
library(caret)
train_stats <- preProcess(df1, method = "range")
new_df1 <- predict(train_stats, df1)
new_df2 <- predict(train_stats, df2)
首先,让我们检查一下是否new_df1
将缩放比例调整为0-1范围。
summary(new_df1)
# some output omitted:
mpg cyl
Min. :0.0000 Min. :0.000
Max. :1.0000 Max. :1.000
现在让我们看看是否在测试集上获得了期望值:
summary(new_df2)
# some output omitted:
mpg cyl
Min. :0.2071 Min. :0.0000
Max. :1.6786 Max. :1.0000
是的,看起来像这样。
现在,仅为了展示如何实现此功能by hand
,请考虑我们需要遍历每一列,执行一个操作,然后返回新列。通常可以使用apply
-family的功能来实现。由于两个不同的数据框涉及相同的列名,因此遍历列名似乎是一个主意。例如,
sapply(names(df1), function(x) (...) )
将应用function
df1中的每个列名称作为参数。让我们以以下方式使用它:
df2[] <- sapply(names(df1), function(col) {
if(is.factor(df2[[col]])) df2[[col]] else (df2[[col]]-min(df1[[col]]))/(max(df1[[col]])-min(df1[[col]]))})
让我们看看这是否能达到预期的结果:
summary(df2)
mpg cyl
Min. :0.2071 Min. :0.0000
Max. :1.6786 Max. :1.0000
它做到了。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句