【问题标题】:Plot smoothed average of third variable by x and y通过 x 和 y 绘制第三个变量的平滑平均值
【发布时间】:2017-02-07 03:49:56
【问题描述】:

我正在尝试制作一个二维图,其中 x 和 y 轴是预测变量。我想顺利总结第三个变量,因为特定坐标的计数非常低。

例如,我可能想绘制针对资产和债务的违约概率。这类似于密度图,但我不想绘制观察值的平滑密度,而是绘制任意平滑值,例如默认率。

我曾尝试在ggplot2 中使用stat_density_2d,但还没有弄清楚如何将第三个变量总结为“密度”而不是观察计数。

样本数据:

data(iris)
plt <- data.frame(iris[c(1,2)], y=as.numeric(iris$Species == "setosa"))

我希望输出看起来像这样:

library(ggplot2)

ggplot(plt, aes(x=Sepal.Length, y=Sepal.Width)) + 
  stat_density_2d(aes(fill= ..density..), geom="tile", contour=FALSE)

但不是颜色代表观察的密度。我希望它代表一个汇总变量。在这种情况下,物种 == “setosa”的概率

【问题讨论】:

  • ggplot2 被认为是“程序员常用的软件工具”。至少R 程序员。
  • 听起来你想要大多数人所说的伪 3D 情节。 (而 ggplot2 历来没有提供这些。)如果您发布一些示例数据,我们可以使用基础图形或点阵图形进行演示。
  • 您的问题不清楚。请提供一些示例(虚构)数据和代码。另见docs.ggplot2.org/current/geom_density_2d.html

标签: r plot ggplot2


【解决方案1】:

UPDATE2:基于discussion in chat,看起来您指的是二维内核平滑函数。 smoothie package 可能有你需要的东西。

无论您如何估计给定 (x,y) 点的贷款违约概率(映射到填充颜色的变量,我在下面将其称为 p.default)(例如,分箱平均值、逻辑回归,内核平滑等),您可以使用以下内容创建绘图:

ggplot(df, aes(assets, debt, fill=p.default)) + geom_tile() 

更新:关于您的评论,对于 iris 示例,您需要对 Sepal.LengthSepal.Width 区域的 y 值进行平均以获得平均概率。这些数据非常稀少,因此您需要相对较大的单元格来获得每个单元格的多个观察值。此外,Sepal.LengthSepal.Width 对于每个物种而言几乎位于完全不同的区域,因此您仍然会在几乎所有单元格中得到全 1 或全 0。在下面的示例中,我只是分配了 1 和 0 的随机值,以便在多个单元格中获得 1 和 0 的混合。

library(ggplot2)
library(dplyr)

# Fake data
set.seed(5)
plt <- data.frame(iris[c(1,2)], y=sample(0:1, nrow(iris), replace=TRUE))

在下面的代码中,我们使用cut 函数将Sepal.LengthSepal.Width 分别分成10 个范围。然后我们平均每个单元格中的 1 和 0,以获得每个单元格的 y 的平均值。然后,这个平均 y 值由填充颜色渐变表示。

plt %>% group_by(Sepal.Length = cut(Sepal.Length, 10),
                 Sepal.Width = cut(Sepal.Width, 10)) %>%
  summarise(y=mean(y)) %>%
  ggplot(aes(Sepal.Width, Sepal.Length, fill=y)) +
  geom_tile() + 
  theme_classic()

或者,我们可以拟合一个逻辑回归模型,它可以为Sepal.LengthSepal.Width 的任意组合提供y 的预测:

# Logistic regression model
m1 = glm(y ~ poly(Sepal.Length,2)*poly(Sepal.Width,2), family="binomial", data=plt)

# Get predictions on a grid of values
df = expand.grid(Sepal.Length=seq(4,8,length=100), Sepal.Width=seq(2,5,length=100))
df$y.pred = predict(m1, newdata=df, type="response")

ggplot(df, aes(Sepal.Width, Sepal.Length, fill=y.pred)) +
  geom_tile() + 
  theme_classic() +
  scale_fill_gradient2(low="blue",mid="yellow",high="red", midpoint=0.5,limits=c(0,1))

一般的想法是,您需要一个值(我们称之为z)与图表上的每个 (x,y) 点相关联。您可以通过对 (x,y) 平面中的区域、模型等进行平均来计算这些 z 值。一旦有了与每个 (x,y) 点对应的 z 值,您就可以生成一个平铺图,其中zfill 美学。

原答案

听起来您可能想要一张热图。填充颜​​色将代表第三个变量的值,在这种情况下为默认概率。也许是这样的:

library(ggplot2)

# Fake data
df = expand.grid(income=seq(1,1e5,length=100), debt=seq(1,5e5,length=100))
df$p.default = df$income - 0.3*df$debt
df$p.default = df$p.default - max(df$p.default)
df$p.default = abs(df$p.default)/max(abs(df$p.default))

ggplot(df, aes(income, debt, fill=p.default)) + 
  geom_tile() +
  scale_fill_gradient2(limits=c(0,1), low="blue", mid="yellow", high="red", midpoint=0.5)

【讨论】:

  • 很接近,但填充变量必须是计算字段。我有一个名为 default 的变量,它的值为 1 和 0。我需要对它们的 x 和 y 值进行平均以创建我的填充颜色。但平均值需要是加权内核平均值,因为大多数唯一 x 和 y 配对通常只有一个数据点。
  • 然后,您只需要通过您使用的任何方法计算每个 (x,y) 对的平均值。然后,该计算字段将成为您的填充变量。如果您提供数据样本(将dput(data_sample) 的输出粘贴到您的问题中)以及您要用于计算每个点的平均值的方法,那么我们可以提供完整的解决方案。
  • 您可以看到一个示例数据集,其中包含我在示例中创建的 plt 对象。 y 变量需要用Sepal.LengthSepal.Width 进行汇总。然而,每一对独特的 Sepal.LengthSepal.Width 通常只有一个观察值。这使得平均值始终为 0 或 1。
  • 感谢您为答案付出的所有努力,因此我会投赞成票。但不幸的是,我无法使用这些解决方案。我认为要汇总的变量的内核密度是最好的。我知道 geom_tile 解决方案,它太离散了。该模型似乎是一个不错的选择,但我正在进行探索性分析,我需要查看真正的关系,而不是建模的关系。
  • 后者可以通过多种方式进行估计(例如,给定资产和债务范围的平均值、逻辑回归、各种机器学习方法等)。但这些会给你一个概率表面(估计的违约概率,以资产和债务的具体价值为条件),而不是计数或百分比。看起来这就是你真正想要的。请指教。
猜你喜欢
  • 2019-08-23
  • 2021-01-17
  • 2021-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-28
  • 2013-01-26
相关资源
最近更新 更多