在 ggplot2 中正确使用 fun.data 和 stat_summary?
Correct use of fun.data with stat_summary in ggplot2?
来自?stat_summary.
fun.data : Complete summary function. Should take data frame as input
and return data frame as output
我无法理解这一点。我的汇总函数 so.summary
似乎根本没有被传递数据框!
代码:
set.seed(0)
so.example <- data.frame(
sampleID=rep(1:15)
, sales=runif(15, 0, 1)*1000
, revenue=runif(15, 0, 1)*10000
)
so.summary <- function(z) {
print(z)
data.frame(sales=median(z$sales), revenue=median(z$revenue))
}
ggplot(
so.example
, aes(x=sales, y=revenue)
) + geom_point() + stat_summary(fun.data=so.summary, geom='point', color='red')
输出:
[1] 2672.207
Error in z$sales : $ operator is invalid for atomic vectors
fun.data
在每个 x
总结 y
。它采用 y
值的向量作为输入。
一个用例是将不同的汇总统计信息映射到不同的美学:
set.seed(0)
week <- floor(runif(30, 1, 5))
sales <- week * runif(30, 0, 1)*10000
so.example <- data.frame(week=week, sales=sales)
so.summary <- function(y) {
return(data.frame(y=median(y), size=length(y), alpha=sd(y)/10000))
}
ggplot(
so.example
, aes(x=week, y=sales)
) + geom_point() + stat_summary(fun.data=so.summary, geom='point', colour='red')
假设您真的想使用统计摘要来绘制该摘要点。正如 logworthy 所指出的,fun.data
将为每个唯一的 x
值接收一个 y
向量。更广泛地说,它为每个独特的 x
值拆分美学 data.frame
(我们稍后会用到这个事实)。但是,如果你改变你的美学,你可以让 stat_summary
看到整个收入向量。
ggplot(so.example) +
geom_point(aes(x=sales, y=revenue)) +
stat_summary(aes(x= median(sales), y= revenue), fun.y= median, geom= 'point', color= 'red')
现在,stat_summary
只能 'see' 1 x
美学和 fun.y
输入中的整个 y
矢量。
如果这还不够 有趣 ,您可以欺骗 fun.data
查看帧的其他向量,例如,假设您需要一个加权平均值而不是中位数。
set.seed(0)
so.example <- data.frame(
sampleID=rep(1:15)
, sales=runif(15, 0, 1)*1000
, revenue=runif(15, 0, 1)*10000
, weight= runif(15, 0, 1)
)
so.mean.weight <- function(x, wt){ sum(x*wt)/sum(wt) }
我创建了一个简单的权重函数,但是,可以轻松地从 stats
中获取 weighted.mean
(更重要的是,该函数显然是任意的,只要它 returns 1 的值输入)。
fun.data
在 data.frame
中查看其他向量的技巧是在函数中从 parent.frame()
中获取额外的美感。这非常 hacky,因为您会收到警告消息。让我们来看看新的 stat_summary
调用:
stat_summary(
aes(x= so.mean.weight(sales, weight), y= revenue, wt= weight)
, fun.data= so.summary
, geom= 'point'
, color= 'darkgreen'
, size= 2
)
注意 aes
、wt= weight
中的输入。在 geom_point
中,没有 wt 美学(你想选择一个你知道不是美学名称的东西(foo/bar 也可以这样做),所以,你会收到一个很好的警告信息告诉你它会被忽略。它会被忽略,但不会removed/deleted。
考虑到这一点,让我们来看看新的 so.summary
函数:
so.summary <- function(z) {
# Grab aesthetic DF
aesDF <- parent.frame()$df
print(names(aesDF)) # returns input aesthetic vectors: "x", "y", "group", and "wt"
pnt <- data.frame(y= so.mean.weight(z, aesDF$wt ) )
print(pnt)
pnt
}
您可以看到对 parent.frame()$df
的调用授予您访问用于计算的美学向量的权限。
来自?stat_summary.
fun.data : Complete summary function. Should take data frame as input and return data frame as output
我无法理解这一点。我的汇总函数 so.summary
似乎根本没有被传递数据框!
代码:
set.seed(0)
so.example <- data.frame(
sampleID=rep(1:15)
, sales=runif(15, 0, 1)*1000
, revenue=runif(15, 0, 1)*10000
)
so.summary <- function(z) {
print(z)
data.frame(sales=median(z$sales), revenue=median(z$revenue))
}
ggplot(
so.example
, aes(x=sales, y=revenue)
) + geom_point() + stat_summary(fun.data=so.summary, geom='point', color='red')
输出:
[1] 2672.207
Error in z$sales : $ operator is invalid for atomic vectors
fun.data
在每个 x
总结 y
。它采用 y
值的向量作为输入。
一个用例是将不同的汇总统计信息映射到不同的美学:
set.seed(0)
week <- floor(runif(30, 1, 5))
sales <- week * runif(30, 0, 1)*10000
so.example <- data.frame(week=week, sales=sales)
so.summary <- function(y) {
return(data.frame(y=median(y), size=length(y), alpha=sd(y)/10000))
}
ggplot(
so.example
, aes(x=week, y=sales)
) + geom_point() + stat_summary(fun.data=so.summary, geom='point', colour='red')
假设您真的想使用统计摘要来绘制该摘要点。正如 logworthy 所指出的,fun.data
将为每个唯一的 x
值接收一个 y
向量。更广泛地说,它为每个独特的 x
值拆分美学 data.frame
(我们稍后会用到这个事实)。但是,如果你改变你的美学,你可以让 stat_summary
看到整个收入向量。
ggplot(so.example) +
geom_point(aes(x=sales, y=revenue)) +
stat_summary(aes(x= median(sales), y= revenue), fun.y= median, geom= 'point', color= 'red')
现在,stat_summary
只能 'see' 1 x
美学和 fun.y
输入中的整个 y
矢量。
如果这还不够 有趣 ,您可以欺骗 fun.data
查看帧的其他向量,例如,假设您需要一个加权平均值而不是中位数。
set.seed(0)
so.example <- data.frame(
sampleID=rep(1:15)
, sales=runif(15, 0, 1)*1000
, revenue=runif(15, 0, 1)*10000
, weight= runif(15, 0, 1)
)
so.mean.weight <- function(x, wt){ sum(x*wt)/sum(wt) }
我创建了一个简单的权重函数,但是,可以轻松地从 stats
中获取 weighted.mean
(更重要的是,该函数显然是任意的,只要它 returns 1 的值输入)。
fun.data
在 data.frame
中查看其他向量的技巧是在函数中从 parent.frame()
中获取额外的美感。这非常 hacky,因为您会收到警告消息。让我们来看看新的 stat_summary
调用:
stat_summary(
aes(x= so.mean.weight(sales, weight), y= revenue, wt= weight)
, fun.data= so.summary
, geom= 'point'
, color= 'darkgreen'
, size= 2
)
注意 aes
、wt= weight
中的输入。在 geom_point
中,没有 wt 美学(你想选择一个你知道不是美学名称的东西(foo/bar 也可以这样做),所以,你会收到一个很好的警告信息告诉你它会被忽略。它会被忽略,但不会removed/deleted。
考虑到这一点,让我们来看看新的 so.summary
函数:
so.summary <- function(z) {
# Grab aesthetic DF
aesDF <- parent.frame()$df
print(names(aesDF)) # returns input aesthetic vectors: "x", "y", "group", and "wt"
pnt <- data.frame(y= so.mean.weight(z, aesDF$wt ) )
print(pnt)
pnt
}
您可以看到对 parent.frame()$df
的调用授予您访问用于计算的美学向量的权限。