r - R设置缺失因子值的默认值
问题描述
我经常使用formula
对象,发现将离散变量重塑为因子非常方便。假设以下示例:
library(caret); library(data.table); data("iris"); iris <- as.data.table(iris)
dummy <- dummyVars(~ -1 + factor(Species,
levels = c("setosa", "versicolor", "virginica")
), data = iris)
predict(dummy, newdata = iris[1,])
它按预期返回正确的帧。
我的问题:
如果给出了新的未定义级别,Species
则因子返回NA
,同时还会弄乱最终输出:
predict(dummy, newdata = iris[1,][, Species:= "something_undefined"])
但是,在某些情况下,将新标签替换为默认值是有用的,即典型/中值标签而不是NA
. 我能想到的一种可能方法是编写一个自定义custom.na.impute
函数来处理这些值并将其用于 default na.action
,即
predict(dummy, newdata = iris[1,][, Species:= "something_undefined"],
na.action = custom.na.impute)
但是,如果我理解正确,在这里我必须为所有不同的因素手动编写规则,并在包含新因素的情况下对其进行更新。相反,我正在寻找这样的东西:
factor(Species, levels = c("setosa", "versicolor", "virginica"),
na.value = "setosa")
也就是说,能够为 any 定义默认/缺失值factor
并直接在公式对象中指定它,而不必乱用 custom na.actions
。
任何想法/建议将不胜感激!
解决方案
评论我自己的问题,因为我无法在现有包中找到更清洁/实现的解决方案。但它可能对某人有用。
无论哪种情况,仍然欢迎更好的解决方案!
factor
解决方案是通过以下方式修改现有功能:
factor2 <- function (x = character(), levels, labels = levels, exclude = NA,
ordered = is.ordered(x), nmax = NA, default = NA)
{
# --- Added rows
if(!is.na(default)){
levels <- unique(c(levels, default))
}
# ---
if (is.null(x))
x <- character()
nx <- names(x)
if (missing(levels)) {
y <- unique(x, nmax = nmax)
ind <- sort.list(y)
y <- as.character(y)
levels <- unique(y[ind])
}
force(ordered)
exclude <- as.vector(exclude, typeof(x))
x <- as.character(x)
levels <- levels[is.na(match(levels, exclude))]
# --- Modified rows
f <- match(x, levels, nomatch = which(levels == default)[1])
# ---
if (!is.null(nx))
names(f) <- nx
nl <- length(labels)
nL <- length(levels)
if (!any(nl == c(1L, nL)))
stop(gettextf("invalid 'labels'; length %d should be 1 or %d",
nl, nL), domain = NA)
levels(f) <- if (nl == nL)
as.character(labels)
else paste0(labels, seq_along(levels))
class(f) <- c(if (ordered) "ordered", "factor")
f
}
现在该default
值要么作为新级别添加,要么在新值不是时更正匹配levels
。
现在预测正在按预期工作:
dummy <- dummyVars(~ -1 + factor2(Species,
levels = c("setosa", "versicolor", "virginica"),
default = "versicolor"
), data = iris)
预测返回正确的默认级别,无需进一步修改任何代码:
predict(dummy, newdata = iris[1,][, Species:= "something_undefined"])
注意:代替factor2
,assignInNamespace('factor', factor2, 'base')
也应该可以工作,尽管它更具侵入性。
推荐阅读
- javascript - 如何拆分模板文字?
- python - 如何在 requirements.txt 中声明一个未合并的直接 github 拉取请求
- ms-access - 如何在 Microsoft Access 中使用 applyfilter 来允许用户输入等于现有表单字段的任何部分?
- python - 如何使用烧瓶 restplus 验证 POST 有效负载中的日期类型?
- string - 查找需要发送的最小消息数
- reactjs - 如何使用 jsx 在导航中添加外部网站链接到 gatsbyjs/react 站点
- amazon-web-services - 禁用后自动清理 CloudFront 分配
- docker - Windows Docker 容器未显示在本地主机上接收“页面不工作”
- docker - Go - 使用 CompileDaemon 的 Docker 自动重载
- gcc - arm-none-eabi-gcc 不从代码中推断浮点乘法累加