gpt4 book ai didi

r - 两个数据帧之间的传输因子属性

转载 作者:行者123 更新时间:2023-12-02 01:49:00 30 4
gpt4 key购买 nike

我建立了一个使用大量(30 个左右)独立因子变量的预测模型。由于我使用的数据集比我机器的 RAM 大得多,我已经对它进行了采样以用于我的训练集和测试集。

我现在希望使用该模型对整个数据集进行预测。我一次拉入 100 万行数据集,每次我都会为我的一些因子变量找到新的水平,这些变量不在我的训练和测试集中,因此阻止模型进行预测。

由于有如此多的独立因子变量(以及如此多的总体观察结果),手动更正每个案例变得非常痛苦。

还有一个问题需要注意:无法保证整个数据帧和训练/测试集中的变量顺序相同,因为我对数据进行预处理会改变它们的顺序。

因此,我想编写一个函数:

  1. 根据新数据的列选择和排序我的采样数据框的配置
  2. 遍历采样数据框和新数据框并指定新数据框中的所有因子水平中相应列中不存在的数据框示例数据框为 Other
  3. 如果我的样本中存在因子水平但新数据框中不存在,则为新数据框中对应的列创建该水平(未分配观察值)。

我已经将#1 放在一起,但不知道执行#2 和#3 的最佳方法。如果是任何其他语言,我会使用 for 循环,但我知道这在 R 中是不受欢迎的。

这是一个可重现的例子:

sampleData <- data.frame(abacus=factor(c("a","b","a","a","a")), montreal=factor(c("f","f","f","f","a")), boston=factor(c("z","y","z","z","q")))
dataset <- data.frame(florida=factor(c("e","q","z","d","b", "a")), montreal=factor(c("f","f","f","f","a", "a")), boston=factor(c("m","y","z","z","r", "f")), abacus=factor(c("a","b","z","a","a", "g")))

sampleData
abacus montreal boston
1 a f z
2 b f y
3 a f z
4 a f z
5 a a q

dataset
florida montreal boston abacus
1 e f m a
2 q f y b
3 z f z z
4 d f z a
5 b a r a
6 a a f g

sampleData <- sample[,order(names(sampleData))]
dataset <- dataset[,order(names(dataset))]
dataset <- dataset[,(colnames(sampleData)]

下面是这个函数完成后我希望 dataset 的样子(我真的不关心 dataset 中列的最终顺序;我我只是认为它是循环(或你们认为最好的)工作所必需的。请注意 dataset$florida 列被省略了:

dataset
montreal boston abacus
1 f Other a
2 f y b
3 f z Other
4 f z a
5 a Other a
6 a Other Other

另请注意,在 dataset 中,boston 的“q”级别没有出现,尽管它出现在 sampleData 中。因此,如果我们从 dataset 中的因素中省略 'q',级别将会不同,这意味着在 'dataset' 中,我们需要 boston 来包含级别 q ,但没有分配给它实际的观察。

最后,请注意,由于我一次对 30 个变量执行此操作,因此我需要一种编程解决方案,而不是使用显式列名称重新分配因子的解决方案。

最佳答案

这似乎可行。

从这个函数中,为 boston 列返回的新级别是 Other y z q,即使级别 q 没有值.关于您在原始问题中的评论,我发现有效应用新因子水平的唯一方法也是像您一样使用 for 循环,到目前为止它对我来说效果很好。

一个函数, findOthers() :

findOthers <- function(newData)  ## might want a second argument for sampleData
{
## take only those columns that are in 'sampleData'
dset <- newData[, names(sampleData)]
## change the 'dset' columns to character
dsetvals <- sapply(dset, as.character)
## change the 'sampleData' levels to character
samplevs <- sapply(sampleData, function(y) as.character(levels(y)))
## find the unmatched elements
others <- sapply(seq(ncol(dset)), function(i){
!(dsetvals[,i] %in% samplevs[[i]])
})
## change the unmatched elements to 'Other'
dsetvals[others] <- "Other"
## create new data frame
newDset <- data.frame(dsetvals)
## get the new levels for each column
newLevs <- lapply(seq(newDset), function(i){
Get <- c(as.character(newDset[[i]]), as.character(samplevs[[i]]))
ul <- unique(unlist(Get))
})
## set the new levels for each column
for(i in seq(newDset)) newDset[,i] <- factor(newDset[,i], newLevs[[i]])
## result
newDset
}

您的示例数据:

sampleData <- data.frame(abacus=factor(c("a","b","a","a","a")), 
montreal=factor(c("f","f","f","f","a")),
boston=factor(c("z","y","z","z","q")))
dataset <- data.frame(florida=factor(c("e","q","z","d","b", "a")),
montreal=factor(c("f","f","f","f","a", "a")),
boston=factor(c("m","y","z","z","r", "f")),
abacus=factor(c("a","b","z","a","a", "g")))

调用 findOthers() 并查看新因子水平的结果:

(new <- findOthers(newData = dataset))
# abacus montreal boston
# 1 a f Other
# 2 b f y
# 3 Other f z
# 4 a f z
# 5 a a Other
# 6 Other a Other

as.list(new)
# $abacus
# [1] a b Other a a Other
# Levels: a b Other
#
# $montreal
# [1] f f f f a a
# Levels: f a
#
# $boston
# [1] Other y z z Other Other
# Levels: Other y z q ## note the new level 'q', with no value in the column

关于r - 两个数据帧之间的传输因子属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23918471/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com