2015-02-19 14 views
5

Próbuję użyć stat_ecdf(), aby narysować skumulowane sukcesy jako funkcję wyniku rankingu utworzonego przez model predykcyjny.W R ggplot2 uwzględnij punkty końcowe stat_ecdf() (0,0) i (1,1)

#libraries 
require(ggplot2) 
require(scales) 

# fake data for reproducibility 
set.seed(123) 
n <- 200 
df <- data.frame(model_score= rexp(n=n,rate=1:n), 
       obs_set= sample(c("training","validation"),n,replace=TRUE)) 
df$model_rank <- rank(df$model_score)/n 
df$target_outcome <- rbinom(n,1,1-df$model_rank) 

# Plot Gain Chart using stat_ecdf() 
ggplot(subset(df,target_outcome==1),aes(x = model_rank)) + 
    stat_ecdf(aes(colour = obs_set), size=1) + 
    scale_x_continuous(limits=c(0,1), labels=percent,breaks=seq(0,1,.1)) + 
    xlab("Model Percentile") + ylab("Percent of Target Outcome") + 
    scale_y_continuous(limits=c(0,1), labels=percent) + 
    geom_segment(aes(x=0,y=0,xend=1,yend=1), 
       colour = "gray", linetype="longdash", size=1) + 
    ggtitle("Gain Chart") 

enter image description here

Wszystko co chcę zrobić, to zmusić ECDF rozpocząć się (0,0) i na koniec (1,1), tak że nie ma przerw na początku lub na końcu krzywa. Jeśli to możliwe, chciałbym zrobić to w ramach składni ggplot2, ale zadowalałoby mnie sprytne obejście tego problemu.

@Henrik to nie jest duplikatem this question, bo już zdefiniowane swoje granice z scale_x_ i _y_continuous() i dodanie expand_limits() nic nie robi. Nie jest to początek PLOT, ale punkty końcowe stat_ecdf(), które wymagają naprawy.

+0

@Henrik - przeczytaj pytanie. Spójrz na moją fabułę. Oczywiście siatka zawiera już (0,0) i (1,1), punkty, które są zawarte w 'geom_segment()', więc nie jest * * kwestią ustalania granic obiektu wydruku. Pytanie dotyczy domeny obiektu "stat_ecdf()", jak podano w tytule mojego pytania. Zobacz, co uważasz za duplikat postu. W ogóle nie jest spokrewniony. – C8H10N4O2

+0

Czy możesz mi powiedzieć, jak to się stało, że masz procent na osi Y? –

+1

@MostafaRifi '+ scale_y_continuous (labels = percent)' i nie zapomnij 'library (scale)' – C8H10N4O2

Odpowiedz

1

Niestety, definicja stat_ecdf nie daje tu miejsca na drgania; określa wewnętrznie punkty końcowe.

Istnieje nieco zaawansowane rozwiązanie. Z najnowszą wersją ggplot2 (devtools::install_github("hadley/ggplot2")) rozszerzalność jest poprawiona, do punktu, w którym możliwe jest obejście tego zachowania, ale nie bez pewnej części.

stat_ecdf2 <- function(mapping = NULL, data = NULL, geom = "step", 
         position = "identity", n = NULL, show.legend = NA, 
         inherit.aes = TRUE, minval=NULL, maxval=NULL,...) { 
    layer(
    data = data, 
    mapping = mapping, 
    stat = StatEcdf2, 
    geom = geom, 
    position = position, 
    show.legend = show.legend, 
    inherit.aes = inherit.aes, 
    stat_params = list(n = n, minval=minval,maxval=maxval), 
    params = list(...) 
) 
} 


StatEcdf2 <- ggproto("StatEcdf2", StatEcdf, 
    calculate = function(data, scales, n = NULL, minval=NULL, maxval=NULL, ...) { 
    df <- StatEcdf$calculate(data, scales, n, ...) 
    if (!is.null(minval)) { df$x[1] <- minval } 
    if (!is.null(maxval)) { df$x[length(df$x)] <- maxval } 
    df 
    } 
) 

Teraz stat_ecdf2 będzie zachowywać się tak samo jak stat_ecdf, ale z opcjonalnym minval i maxval parametru. Więc będzie to rade:

ggplot(subset(df,target_outcome==1),aes(x = model_rank)) + 
    stat_ecdf2(aes(colour = obs_set), size=1, minval=0, maxval=1) + 
    scale_x_continuous(limits=c(0,1), labels=percent,breaks=seq(0,1,.1)) + 
    xlab("Model Percentile") + ylab("Percent of Target Outcome") + 
    scale_y_continuous(limits=c(0,1), labels=percent) + 
    geom_segment(aes(x=0,y=0,xend=1,yend=1), 
       colour = "gray", linetype="longdash", size=1) + 
    ggtitle("Gain Chart") 

Dużą zastrzeżenie jest to, że ja nie wiem, czy obecny model rozciągliwość będą wspierane w przyszłości; w przeszłości kilkakrotnie się zmieniało, a zmiana na "ggproto" jest ostatnia - jak ostatnio 15 lipca 2015 r.

Dało mi to szansę, aby naprawdę zagłębić się w elementy wewnętrzne ggplota, co jest czymś, co zamierzałem zrobić przez jakiś czas.

+0

Wiele nauczyłem się z tej odpowiedzi - dzięki. Znacznie lepsze niż moje obejście, które tworzyło fałszywe punkty danych (na ryzyko zniekształcenia ekdf, przynajmniej na mniejszych zbiorach danych). Tworzy to atrapę punktów na samym wykresie. – C8H10N4O2

Powiązane problemy