2012-03-01 7 views
6

Я использую dlply() с пользовательской функцией, которая усредняет наклоны lm() для данных, содержащих некоторые значения NA, и Я получаю ошибку "ошибка в lm.fit (х, у, смещение = смещение, singular.ok = singular.ok, ...): 0 (не NA) случаи"lm вызван изнутри dlply throws «0 (non-NA) cases» error [r]

Эта ошибка происходит только когда я вызываю dlply с двумя ключевыми переменными - разделение на одну переменную отлично работает.

Раздражающе, я не могу воспроизвести ошибку с помощью простого набора данных, поэтому я разместил набор данных проблем в своем Dropbox.

Вот код, как и свести к минимуму, насколько это возможно, все еще производит ошибку:

masterData <- read.csv("http://dl.dropbox.com/u/48901983/SOquestionData.csv", na.strings="#N/A") 

workingData <- data.frame(sample = masterData$sample, 
         substrate = masterData$substrate, 
         el1 = masterData$elapsedHr1, 
         F1 = masterData$r1 - masterData$rK) 

#This function is trivial as written; in reality it takes the average of many slopes 
meanSlope <- function(df) { 
    lm1 <- lm(df$F1 ~ df$el1, na.action=na.omit) #changing to na.exclude doesn't help 
    slope1 <- lm1$coefficients[2] 
    meanSlope <- mean(c(slope1)) 
} 

lsGOOD <- dlply(workingData, .(sample), meanSlope) #works fine 

lsBAD <- dlply(workingData, .(sample, substrate), meanSlope) #throws error 

Заранее спасибо за любую проницательность.

+1

Я бы сказал, что ошибка информативна. Если вы посмотрите на значения в каждом подмножестве своих данных, я предполагаю, что вы найдете одно подмножество всего 'NA'. Попробуйте заменить свой вызов lm в своей функции тем, что может идентифицировать 'all (is.na())'. – Justin

ответ

5

Для некоторых из ваших перекрестных классификаций у вас есть недостающий ковариат:

with(masterData, table(sample, substrate, r1mis = is.na(r1))) 
# 
snipped the nonmissing reports 
, , r1mis = TRUE 

     substrate 
sample 1 2 3 4 5 6 7 8 
    3 0 0 0 0 0 0 0 0 
    4 0 0 0 0 0 0 0 0 
    5 0 0 0 0 0 0 0 0 
    6 0 0 0 0 0 0 0 0 
    7 0 0 0 0 0 0 3 3 
    8 0 0 0 0 0 0 0 3 
    9 0 0 0 0 0 0 0 3 
    10 0 0 0 0 0 0 0 3 
    11 0 0 0 0 0 0 0 3 
    12 0 0 0 0 0 0 0 3 
    13 0 0 0 0 0 0 0 3 
    14 0 0 0 0 0 0 0 3 

Это позволит вам пропустить подмножества с недостаточным данные по этим конкретным данным:

meanSlope <- function(df) { if (sum(!is.na(df$el1)) < 2) { return(NA) } else { 
    lm1 <- lm(df$F1 ~ df$el1, na.action=na.omit) #changing to na.exclude doesn't help 
    slope1 <- lm1$coefficients[2] 
    meanSlope <- mean(c(slope1)) } 
} 

Хотя это зависит от отсутствия пропусков в одном конкретном ковариате. Более надежным решением было бы использовать try для захвата ошибок и преобразования в NA.

?try 
+0

О, я вижу - я не получил что lm() выбрасывает ошибки вместо NA.Это полезный совет. –

+0

Способ увидеть, что бросает ошибку, это выполнить 'traceback()'. –

2

В соответствии с моим комментарием:

my.func <- function(df) { 
    data.frame(el1=all(is.na(df$el1)), F1=all(is.na(df$F1))) 
} 

ddply(workingData, .(sample, substrate), my.func) 

показывает, что у вас есть много наборов юга, где оба F1 и el1 являются NA. (На самом деле каждый раз, когда один все па, а другой, как хорошо!)

+0

Благодаря вам и @DWin для этого момента - вещь, которую я не понимаю, как я могу получить dlply(), чтобы поместить склоны в элементы списка, когда они доступны, и NA (или аналогичные), когда они не? Я думал, что dlply работает над подмножествами фреймов более или менее независимо, так что NA в одном подмножестве не будет мешать другим подмножествам, но я предполагаю, что это не так. –

+0

Более ясно - один из способов обработки НС заключался в том, чтобы заманить их в функцию MeanSlope, но я чувствую, что должен быть лучший способ ... –

+0

'dlply' здесь не виноват. он обрабатывает каждое подмножество независимо, как вы ожидали. однако, если вы подаете подмножество в 'lm', то есть все NA, это приведет к ошибке. вы пытались обработать случай, когда некоторые значения были NA правильно, но вы не можете подавать 'lm' пустую подмножество, что и есть, если вы' na.omit' подмножество со всеми NA. вместо этого добавьте строку, подобную 'if (all (is.na (df)) return (NA)' перед вызовом 'lm'. – Justin