В ggplot ограничить y быть> 0 в LOESS - PullRequest
9 голосов
/ 06 мая 2010

Вот мой код:

#data
sites <- 
  structure(list(site = c(928L, 928L, 928L, 928L, 928L, 928L, 928L,
                          928L, 928L, 928L, 928L, 928L, 928L, 928L,
                          928L, 928L, 928L, 928L, 928L, 928L, 928L,
                          928L, 928L, 928L, 928L, 928L), 
                 date = c(13493L, 13534L, 13566L, 13611L, 13723L,
                          13752L, 13804L, 13837L, 13927L, 14028L,
                          14082L, 14122L, 14150L, 14182L, 14199L,
                          16198L, 16279L, 16607L, 16945L, 17545L,
                          17650L, 17743L, 17868L, 17941L, 18017L, 18092L),
                 y = c(7L, 7L, 17L, 18L, 17L, 17L, 10L, 3L, 17L, 24L, 
                       11L, 5L, 5L, 3L, 5L, 14L, 2L, 9L, 9L, 4L, 7L,
                       6L, 1L, 0L, 5L, 0L)), 
            .Names = c("site", "date", "y"),
            class = "data.frame", row.names = c(NA, -26L))

#convert to date
x<-as.Date(sites$date, origin="1960-01-01") 

#plot smooth, line goes below zero!
qplot(data=sites, x, y, main="Site 349") 
(p <- qplot(data = sites, x, y, xlab = "", ylab = ""))
(p1 <- p + geom_smooth(method = "loess",span=0.5, size = 1.5))

Некоторые из LOESS линий и доверительных интервалов идут ниже нуля, я хотел бы ограничить графику 0 и положительными числами (потому что отрицательные не имеют смысла),enter image description here

Как я могу это сделать?

Ответы [ 2 ]

15 голосов
/ 06 мая 2010

Я поддерживаю предложение Мэтта Паркера, чтобы вы изменили процедуру подгонки. Один вариант, который часто работает только для положительных данных, - это выполнить подбор в логарифмическом масштабе, а затем возвести в степень, чтобы получить результаты в исходном масштабе. Это гарантирует только положительные значения.

Генерация случайных данных, которые имеют некоторые из этих проблем:

 d <- data.frame(x=0:100)
 d$y <- exp(rnorm(nrow(d), mean=-d$x/40, sd=0.8))
 qplot(x,y,data=d) + stat_smooth() 

Теперь мы можем использовать возможности преобразования ggplot для лог-преобразования значений y, но отображать результаты в экспоненциальном масштабе (который соответствует исходному):

qplot(x,y,data=d) + stat_smooth() + scale_y_log10()+coord_trans(ytrans="pow10")

Примеры можно увидеть на странице справки coord_trans. Если вам не нравится ось Y, вы можете манипулировать разрывами и метками.

РЕДАКТИРОВАТЬ на основе обновления вопроса

В ggplot2 произошли некоторые изменения с тех пор, как вопрос был задан изначально, и первоначальный ответ не касался 0.

Вариант 1

Основная идея решения та же: найти преобразование, которое отобразит диапазон возможных значений с -Inf на Inf, выполнить сглаживание лесса и затем выполнить обратное преобразование результата. Лог-преобразование было бы замечательно, если бы не было нулей. Я не думаю, что необходимая функция существует, если включен 0, но часто работающая возможность - это преобразование log(1+x). Это встроено, но нам нужно иметь обратное преобразование exp(x)-1.

library(scales)
#create exp(x)-1 transformation, the inverse of log(1+p)
expm1_trans <-  function() trans_new("expm1", "expm1", "log1p")

qplot(x, y, data=sites) + stat_smooth(method="loess") +
  scale_y_continuous(trans=log1p_trans()) +
  coord_trans(ytrans=expm1_trans())

Loess fit on log(1+x) transformed data

Вариант 2

Второй вариант расширяет предложение в комментариях к ответу Мэтта Паркера: используйте метод регрессии, который включает в себя целочисленный характер результатов. Это означает избыточную (на всякий случай) регрессию Пуассона для отсчетов. Хотя вы не можете сделать лесс, вы можете сделать подгонку сплайна. Вы можете играть со степенями свободы, чтобы контролировать плавность.

library(splines)
qplot(x, y, data=sites) + stat_smooth(method="glm", family="quasipoisson", 
                                      formula = y ~ ns(x, 3))

Spline fit using overdispersed Poisson regression

Два варианта дают очень похожие результаты, и это хорошо.

4 голосов
/ 06 мая 2010

Я не могу проверить это без некоторых примеров данных, но

qplot(data=sites, x, y, main="Site 349")  
(p <- qplot(data = sites, x, y, xlab = "", ylab = "")) 
(p1 <- p + geom_smooth(method = "loess",span=0.5, size = 1.5)) 
p1 + theme_bw() + opts(title = "Site 349") + ylim(0, foo)

(где foo - подходящий верхний предел для вашего графика) может помочь. В отличие от базовой графики, команды xlim () и ylim () в ggplot фактически ограничивают данные, которые используются при создании графика, а не только окно графика. Это также может ограничить geom_smooth() (хотя я не уверен).

Редактировать: Прочитав немного больше, вы также можете подумать об отключении модели, используемой geom_smooth. Опять же, неспособность увидеть ваши данные - это проблема. Но, например, если он бинарный - вы можете добавить stat_smooth(method="glm", family="binomial"), чтобы получить сглаженную логит-строку. Смотри ?stat_smooth для больше.

...