在 R ggplot2 中,包括 stat_ecdf() 端点 (0,0) 和 (1,1)
In R ggplot2, include stat_ecdf() endpoints (0,0) and (1,1)
我正在尝试使用 stat_ecdf()
将累积成功绘制为预测模型创建的排名分数的函数。
#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")
我想做的就是强制 ECDF 从 (0,0) 开始并在 (1,1) 结束,这样曲线的开头或结尾就没有间隙。如果可能的话,我想在 ggplot2
的语法内完成它,但我会接受一个聪明的解决方法。
@Henrik 这不是 this question 的副本,因为我已经用 scale_x_
和 _y_continuous()
定义了我的限制,并且添加 expand_limits()
不起作用任何事物。需要修复的不是 PLOT 的起点,而是 stat_ecdf() 的端点。
不幸的是,stat_ecdf
的定义在这里没有回旋余地;它在内部确定端点。
有一个比较高级的解决方案。使用最新版本的 ggplot2 (devtools::install_github("hadley/ggplot2")
),可扩展性得到改进,可以覆盖此行为,但并非没有一些样板。
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
}
)
现在,stat_ecdf2
的行为与 stat_ecdf
相同,但具有可选的 minval
和 maxval
参数。所以这会成功:
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")
这里最大的警告是,我不知道将来是否会支持当前的扩展模型;它过去已经更改过几次,使用 "ggproto" 的更改是最近的 -- 比如 2015 年 7 月 15 日最近。
另外,这让我有机会真正深入了解 ggplot 的内部结构,这是我一直想做的事情。
我正在尝试使用 stat_ecdf()
将累积成功绘制为预测模型创建的排名分数的函数。
#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")
我想做的就是强制 ECDF 从 (0,0) 开始并在 (1,1) 结束,这样曲线的开头或结尾就没有间隙。如果可能的话,我想在 ggplot2
的语法内完成它,但我会接受一个聪明的解决方法。
@Henrik 这不是 this question 的副本,因为我已经用 scale_x_
和 _y_continuous()
定义了我的限制,并且添加 expand_limits()
不起作用任何事物。需要修复的不是 PLOT 的起点,而是 stat_ecdf() 的端点。
不幸的是,stat_ecdf
的定义在这里没有回旋余地;它在内部确定端点。
有一个比较高级的解决方案。使用最新版本的 ggplot2 (devtools::install_github("hadley/ggplot2")
),可扩展性得到改进,可以覆盖此行为,但并非没有一些样板。
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
}
)
现在,stat_ecdf2
的行为与 stat_ecdf
相同,但具有可选的 minval
和 maxval
参数。所以这会成功:
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")
这里最大的警告是,我不知道将来是否会支持当前的扩展模型;它过去已经更改过几次,使用 "ggproto" 的更改是最近的 -- 比如 2015 年 7 月 15 日最近。
另外,这让我有机会真正深入了解 ggplot 的内部结构,这是我一直想做的事情。