使用带有dplyr的线性模型捕获NAs

时间:2015-09-02 14:22:55

标签: r dplyr

这是一个exmaple数据框

library(dplyr)
df <- data.frame(id=c(1,1,1,2,2,2),
   v2=factor(c("a","c","c","a","b","d")),
   v3=c(1,NA,NA,6,7,9),
   v4=c(5:10))

请注意,v3包含NAs,因此当我尝试为每个id拟合线性模型时,我收到错误:

slope <- df %>% filter(v2=="c") %>% 
  group_by(id) %>% 
  do(fit = lm(v3 ~ v4, .)) %>%
  summarise(slope = coef(fit)[2])

Error in lm.fit(x, y, offset = offset, singular.ok = singular.ok, ...)   : 
  0 (non-NA) cases

如果只存在NAs,如何捕获此错误并将其替换为默认值。

请注意,v4也有NAs,如果v3 = c(1,NA), v4 = c(NA,2)它也无法构建线性模型。

例如,如果df不包含任何“c”,那么我可以轻松地使用

if(nrow(slope) == 0) slope <- 0

因为那么斜率是一个空数据帧。

2 个答案:

答案 0 :(得分:3)

我们可以在if/else中使用do条件来检查NA元素。如果all中的元素NA位于&#39; v3&#39;或(|)&#39; v4&#39;,它应返回斜率为NA或else执行lm并获取斜率值。

df %>% 
  filter(v2=='c') %>%
  group_by(id) %>%
  do({if(all(is.na(.$v3))|all(is.na(.$v4))) 
              data.frame(slope=NA) 
             else data.frame(slope=coef(lm(v3~v4, .))[2])}) %>%
  slice(1L) %>% 
  ungroup() %>%
  select(-id)

数据

df <- data.frame(id=c(1,1,1,2,2,2, 3, 3, 3,3, 3, 4, 4),
 v2=factor(c("a","c","c","a","b","d", "c", "c", "a", "c", "c", "c", "c")),
 v3=c(1,NA,NA,6,7,9, NA, 1, NA, 5,8, NA, 5 ),
 v4=c(5:17))

答案 1 :(得分:1)

如果您确实在问“我怎样才能抓住此错误”,您可以尝试 tryCatch

根据具体情况,这可能会更有用,它只会忽略"0 (non-NA) cases"消息的错误,而且您不必进行混乱的数据检查。

您也可以在failwith包中使用plyr,但我相信会捕获所有错误消息。但是它使用起来更简单。

all_na_msg <- "0 (non-NA) cases";
trymodel <- function(df, default = NA) {
  tryCatch(lm(v3 ~ v4, df),
           error = if (e$message == all_na_msg)
                     default
                   else
                     stop(e));
}

slope <- df %>% filter(v2=="c") %>% 
  group_by(id) %>% 
  do(fit = trymodel(df)) %>%
  summarise(slope = coef(fit)[2])