在ggplot2中正确使用fun.data和stat_summary?

log*_*thy 5 r ggplot2

来自?stat_summary。

fun.data:完整的摘要功能。应将数据帧作为输入,并将返回数据帧作为输出

我很难理解这一点。似乎我的摘要函数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')
Run Code Online (Sandbox Code Playgroud)

输出:

[1] 2672.207
Error in z$sales : $ operator is invalid for atomic vectors
Run Code Online (Sandbox Code Playgroud)

小智 6

假设您确实想使用统计摘要来绘制该摘要点。正如 logworthy 所指出的,每个唯一值fun.data都会收到一个向量。更广泛地说,它将美学划分为每个独特的值(我们稍后将使用这个事实)。但是,如果你改变你的美学,你可以看到整个收入向量。yxdata.framexstat_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')
Run Code Online (Sandbox Code Playgroud)

现在,stat_summary只能“看到”输入中的1 种x美学和整个向量。yfun.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) }
Run Code Online (Sandbox Code Playgroud)

我创建了一个简单的权重函数,但是可以轻松获取weighted.meanstats更重要的是,该函数显然是任意的,只要它为输入返回 1 个值)。

fun.data在 中查看其他向量的技巧是从函数中的 while 中data.frame获得额外的美感。parent.frame()这非常棘手,因为您会收到警告消息。让我们看一下新的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
    )
Run Code Online (Sandbox Code Playgroud)

aes注意,中的输入wt= weight。在 中geom_point,没有 wt 美学(您想要选择一些您知道不是美学名称的名称(foo/bar 也可以),因此,您会收到一条很好的警告消息,告诉您它将被忽略。它将被忽略,但不会被删除/删除。

考虑到这一点,让我们看看新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
}
Run Code Online (Sandbox Code Playgroud)

您可以看到对授予parent.frame()$df您访问美学向量以在计算中使用的调用。


log*_*thy 5

fun.datay在每个总结x。它以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')
Run Code Online (Sandbox Code Playgroud)