按因子水平对观察值进行子设置,且超过x个观察值

时间:2019-08-14 13:21:41

标签: r subset factors

我有一个数据集,其中一个因素具有很多水平(+/- 140),因为lm函数因以下原因而失效:

Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
  contrasts can be applied only to factors with 2 or more levels

我想做的是将lm函数子集化,仅使用观察到超过x个观测值的因子水平。

例如,此data.table具有一个因子(some_NA_factor),对此级别1, 2 , 4, 5具有17个观测值,而级别3具有16个观测值。我想直接lm-function)子集的数据集仅使用因子水平具有16个(至少17个)观察值的观察值:

set.seed(1)
library(data.table)
DT <- data.table(panelID = sample(50,50),                                                    # Creates a panel ID
                      Country = c(rep("A",30),rep("B",50), rep("C",20)),       
                      some_NA = sample(0:5, 6),                                             
                      some_NA_factor = sample(0:5, 6),         
                      Group = c(rep(1,20),rep(2,20),rep(3,20),rep(4,20),rep(5,20)),
                      Time = rep(seq(as.Date("2010-01-03"), length=20, by="1 month") - 1,5),
                      norm = round(runif(100)/10,2),
                      Income = sample(100,100),
                      Happiness = sample(10,10),
                      Sex = round(rnorm(10,0.75,0.3),2),
                      Age = round(rnorm(10,0.75,0.3),2),
                      Educ = round(rnorm(10,0.75,0.3),2))           
DT [, uniqueID := .I]                                                                        # Creates a unique ID     
DT[DT == 0] <- NA                                                                            # https://stackoverflow.com/questions/11036989/replace-all-0-values-to-na
DT$some_NA_factor <- factor(DT$some_NA_factor)
table(DT$some_NA_factor)

例如lm中的普通子集语法如下:

lm(Happiness ~ Income + some_NA_factor, data=DT, subset=(Income > 50 & Happiness < 5))

如何修改语法以检查对因子水平的观察?

2 个答案:

答案 0 :(得分:2)

请考虑通过Filter调用中的isTRUEtable构建布尔向量,然后在 subset 参数中运行%in%

boolean_vec <- Filter(isTRUE, table(DT$some_NA_factor) > 16)
boolean_vec
#    1    2    4    5 
# TRUE TRUE TRUE TRUE 

lm(Happiness ~ Income + some_NA_factor, data=DT, 
   subset=(Income > 50 & Happiness < 5 & some_NA_factor %in% names(boolean_vec)))

答案 1 :(得分:1)

或者使用dplyr中的%>%函数,因此您不必分别存储每个子集:

library(dplyr)
DT %>% filter(!is.na(some_NA_factor)) %>% 
count(some_NA_factor) %>% filter(n > 16) %>% inner_join(DT, by = 
'some_NA_factor') %>%
lm(Happiness ~ Income + some_NA_factor, data = .)