确保model.matrix的列数与列车和测试集的列数相同

确保model.matrix的列数与列车和测试集的列数相同,r,R,是否有办法确保模型矩阵中的列数与列车和测试集的列数相同 我尝试了以下方法: library(tidyverse) create_encoder <- function(x){ cat_vars <- x[1, ] %>% select_if(is.factor) %>% names() labels_dic <- cat_vars %>% map(~x %>% pull(.) %>% levels) %>% set_nam

是否有办法确保模型矩阵中的列数与列车和测试集的列数相同

我尝试了以下方法:

library(tidyverse)

create_encoder <- function(x){
  cat_vars <- x[1, ] %>% select_if(is.factor) %>% names()
  labels_dic <- cat_vars %>% map(~x %>% pull(.) %>% levels) %>% 
    set_names(cat_vars)
  encode_test <- function(x){
    y <- x
    y[, cat_vars] <- cat_vars %>%
      map(~factor(x %>% pull(.), labels_dic[[.]]))
    y
  }
}

x_ent <- tibble(x1 = c(1, 2, 3, 4), x2 = c('a', 'b', 'a', 'c'))
x_pr <- tibble(x1 = c(5, 6, 7), x2 = c('a', 'b', 'a'))
x_ent <- x_ent %>% mutate_if(is.character, as.factor)
x_pr <- x_pr %>% mutate_if(is.character, as.factor)

y_ent <- c(2, 1, 3, 4)
y_pr <- c(6, 3, 2)

encode_test <- create_encoder(x_ent)
x_pr <- encode_test(x_pr)

x_mat_ent <- model.matrix(~., x_ent)
x_mat_pr <- model.matrix(~., x_pr)

x_mat_ent
x_mat_pr

x_mat_ent %>% dim()
x_mat_pr %>% dim()
库(tidyverse)
创建\u编码器%names()
标签\u dic%映射(~x%%>%pull(%)%%>%levels)%%>%
设置名称(类别变量)

encode_test首先,我假设您不是指维度,而是指列的数量,我们希望行的数量不同,因为变量长度不同

我认为这是一个很好的例子,说明tidyverse将一些非常简单的问题复杂化:

library(tidyverse)

x_ent <- tibble(x1 = c(1, 2, 3, 4), x2 = factor(c('a', 'b', 'a', 'c'), levels = letters[1:3]))
x_pr <- tibble(x1 = c(5, 6, 7), x2 = factor(c('a', 'b', 'a'), levels = letters[1:3]))

x_mat_ent <- model.matrix(~., x_ent)
x_mat_pr <- model.matrix(~., x_pr)

x_mat_ent %>% dim()
x_mat_pr %>% dim()
对于forcats:

library(tidyverse)
library(magrittr)

set.seed(1)

x_ent <- tibble(x1 = runif(100), x2 = factor(rbinom(100, 100, 0.5))); 
x_pr <- tibble(x1 = runif(100), x2 = factor(rbinom(100, 500, 0.5)))

x_ent %<>% mutate(x2 = fct_expand(x2, lvls_union(list(x_ent$x2, x_pr$x2))))
x_pr %<>% mutate(x2 = fct_expand(x2, lvls_union(list(x_ent$x2, x_pr$x2))))

x_mat_ent <- model.matrix(~., x_ent)
x_mat_pr <- model.matrix(~., x_pr)

x_mat_ent %>% dim()
x_mat_pr %>% dim()
库(tidyverse)
图书馆(magrittr)
种子(1)

x_ent您也可以在函数中传递列车数据帧,以获得要设置的级别

library(dplyr)

create_encoder <- function(test, train){
  cols <- sapply(test, is.character)
  test[cols] <- purrr::map2(test %>% select(where(is.character)), 
                     train %>% select(where(is.factor)), 
                     ~factor(.x, levels = levels(.y))
                    )
  test
}

x_ent <- tibble(x1 = c(1, 2, 3, 4), x2 = c('a', 'b', 'a', 'c'))
x_pr <- tibble(x1 = c(5, 6, 7), x2 = c('a', 'b', 'a'))
x_ent <- x_ent %>% mutate(across(where(is.character), factor))
x_pr <- create_encoder(x_pr, x_ent)
x_mat_ent <- model.matrix(~., x_ent)
x_mat_pr <- model.matrix(~., x_pr)

x_mat_ent %>% dim()
#[1] 4 4
x_mat_pr %>% dim()
#[1] 3 4
库(dplyr)

创建编码器是。我的意思是相同数量的列。我已经编辑了这个问题,所以现在问题清楚了。关于您的示例,如果数据集更大,如何自动执行此操作?我添加了第二个示例来演示此问题。这将是一个功能的全部。但是,难道没有类似于python OneHotEncoder的东西吗?我不知道python OneHotEncoder做什么。python中的sklearn模块有OneHotEncoder类,它获取一个热编码矩阵,并轻松处理分类变量的标签。到目前为止,我还没有找到一个R函数,它可以自动进行一次热编码,并处理train和testset中分类变量的标签数量之间的差异。
library(dplyr)

create_encoder <- function(test, train){
  cols <- sapply(test, is.character)
  test[cols] <- purrr::map2(test %>% select(where(is.character)), 
                     train %>% select(where(is.factor)), 
                     ~factor(.x, levels = levels(.y))
                    )
  test
}

x_ent <- tibble(x1 = c(1, 2, 3, 4), x2 = c('a', 'b', 'a', 'c'))
x_pr <- tibble(x1 = c(5, 6, 7), x2 = c('a', 'b', 'a'))
x_ent <- x_ent %>% mutate(across(where(is.character), factor))
x_pr <- create_encoder(x_pr, x_ent)
x_mat_ent <- model.matrix(~., x_ent)
x_mat_pr <- model.matrix(~., x_pr)

x_mat_ent %>% dim()
#[1] 4 4
x_mat_pr %>% dim()
#[1] 3 4