进行热图,水平/等高线图和六边形分级的方法

时间:2011-10-21 15:23:07

标签: r plot ggplot2

R中(x,y,z)的2D图的选项有点多。然而,解决这些选择是一个挑战,特别是在所有三个都是连续的情况下。

为了澄清问题(并且可能有助于解释为什么我可能会被contourimage绊倒),这里有一个可能的分类方案:

  • 情况1:未提供z的值,而是基于(x,y)中的值的条件密度。 (注意:这基本上是将z的计算降级为单独的函数 - 密度估计。某些东西仍然必须使用该计算的输出,因此允许任意计算会很好。)
  • 案例2:(x,y)对是唯一且规则间隔的。这意味着每个(x,y)值只提供一个z值。
  • 案例3:(x,y)对是唯一的,但是是连续的。着色或着色仍然只由1个唯一的z值决定。
  • 案例4:(x,y)对不是唯一的,但是有规律地间隔开。着色或着色由z值上的聚合函数确定。
  • 案例5:(x,y)对不是唯一的,是连续的。着色/着色必须由z值上的聚合函数确定。

如果我遗漏了一些情况,请告诉我。我感兴趣的案例是#5。关于人际关系的一些注释:

  • 案例#1似乎已得到很好的支持。
  • heatmapimage以及ggplot中的功能轻松支持案例#2。
  • 案例#3受基础plot支持,但使用颜色渐变留给用户。
  • 案例#4可以通过使用拆分&应用功能。我以前做过那个。
  • 案例#5可以使用cut转换为#4(然后是#2),但这是不优雅和四四方方的。十六进制分箱可能更好,但这似乎不容易取决于z的值是否存在陡峭的梯度。我决定使用十六进制分箱,但非常欢迎其他聚合功能,特别是如果它们可以使用z值。

我怎么能做#5?下面是生成鞍座的代码,尽管spread的值会改变z值的扩展,这会在绘制渐变时产生差异。

N       = 1000
spread  = 0.6   # Vals: 0.6, 3.0
set.seed(0)
rot     = matrix(rnorm(4), ncol = 2)
mat0    = matrix(rnorm(2 * N), ncol = 2)
mat1    = mat0 %*% rot
zMean   = mat0[,2]^2 - mat0[,1]^2
z       = rnorm(N, mean = zMean, sd = spread * median(abs(zMean)))

我想做一些像hexbin这样的事情,但我已经用ggplot对此进行了攻击并且没有取得多大进展。如果我可以将任意聚合函数应用于区域中的z值,那就更好了。 (这种功能的形式可能类似于plot(mat1, colorGradient = f(z), aggregation = "bin", bins = 50)。)

如何在ggplot或其他包中执行此操作?我很高兴将这个问题作为社区维基问题(或者其他用户可以通过编辑足够多次)。如果是这样,请为每个帖子提供一个答案,以便我们可以专注于ggplotlevelplotlatticecontourplot(或image)和其他选项,如果存在的话。


更新1:volcano example是案例#3的一个很好的例子:数据有规律地间隔(可以是纬度/经度),每次观察一个z值。地形图具有(纬度,经度,海拔高度),因此每个位置具有一个值。假设一个人在很多天内获得了许多随机放置的传感器的天气(例如降雨,风速,太阳光):这更像是#5而不是#3 - 我们可能有lat&很长,但z值可以相当大,即使是相同或附近的(x,y)值。

更新2:到目前为止,DWin,Kohske和John Colby的答案都非常出色。我的实际数据集是一个较大集合的小样本,但在200K点它产生有趣的结果。在(x,y)平面上,它在一些区域具有非常高的密度(因此,在那些区域中会出现过度绘图)并且在其他区域中密度低得多或完全不存在。根据John fields提出的建议,我需要对Tps的数据进行二次抽样以便计算出来(我将调查是否可以在不进行二次抽样的情况下进行),但结果非常有趣。尝试rms / Hmisc(DWin的建议),全部200K积分似乎运作良好。 Kohske的建议相当不错,并且,在绘图之前将数据转换为网格,输入数据点的数量没有问题。它还为我提供了更大的灵活性,可以确定如何聚合区域中的z值。我还不确定我是否会使用均值,中位数或其他聚合。

我还打算用其他方法尝试Kohske的mutate + ddply的好例子 - 它是如何在给定区域内计算不同统计数据的一个很好的例子。


更新3:虽然没有明显的赢家,但不同的方法是截然不同的,有几种方法是显着的。我选择约翰科尔比作为第一个答案。我想我会在进一步的工作中使用它或DWin的方法。

4 个答案:

答案 0 :(得分:5)

我对这类问题的fields软件包运气很好。以下是使用Tps表示薄板样条线的示例:

编辑:组合图并添加标准错误

require(fields)

dev.new(width=6, height=6)
set.panel(2,2)

# Plot x,y
plot(mat1)

# Model z = f(x,y) with splines
fit = Tps(mat1, z)
pred = predict.surface(fit)

# Plot fit
image(pred)
surface(pred)

# Plot standard error of fit 
xg = make.surface.grid(list(pred$x, pred$y))
pred.se = predict.se(fit, xg)

surface(as.surface(xg, pred.se))

enter image description here

答案 1 :(得分:3)

我通常使用rms / Hmisc包组合。这是使用交叉三次样条项的线性回归分析(函数ols),其绘制的输出非常类似于提供的字段示例:

dfrm <- data.frame(z=z, xcor = mat1[,1], ycor=mat1[,2])
require(rms)  # will automatically load Hmisc which needs to have been installed
lininterp <- ols(z ~ rcs(xcor,3)*rcs(ycor,3), data=dfrm)
ddI <- datadist(dfrm)
options(datadist="ddI")

 bplot(Predict(lininterp, xcor, ycor))  # Plot not shown
 perim <- with(dfrm, perimeter(xcor, ycor))
 bplot(Predict(lininterp, xcor, ycor), perim=perim)  
# Plot attached after converting to .png

您还可以在我对此问题的回答的第二部分中看到一种不依赖于三维表面回归估计的方法:Using color as the 3rd dimension

enter image description here 绘图范例是格子,您还可以获得等高线图以及这个漂亮的水平图。如果您希望预测值位于某个点,那么您可以使用应用于fit-object的Predict函数来获取该值。

答案 2 :(得分:3)

panel.2dsmoother包中有latticeExtra个功能:

library(lattice)
library(latticeExtra)

df <- data.frame(mat1, z)
names(df)[c(1,2)] <- c('x', 'y')

levelplot(z ~ x * y, data = df, panel = panel.2dsmoother, contour=TRUE)

panel.2dsmoother

根据其help page,平滑模型(近似)构造为方法(形式,数据=列表(x = x,y = y,z = z),{args})[... ]这应该适用于任何采用公式参数的模型函数,并且具有预测方法参数“。

答案 3 :(得分:2)

问题可以分为两部分。第一个是聚合数据,第二个是可视化数据。

正如@John所示,

fields包可以同时执行这些操作。 在ggplot2中,如果汇总只是数据的计数,则stat_bin2d可用。

无论如何,如果你想要你自己的聚合函数,也许这样的东西会有所帮助:

df <- data.frame(x = mat1[,1], y = mat1[,2], z = z)

Nx <- 10 # nubmer of bins for x
Ny <- 4  # number of bins for y

# create a data.
df2 <- mutate(ddply(df, .(x = cut(x, Nx), y = cut(y, Ny)), summarise, 
                    Mean = mean(z),
                    Var = var(z)),
              xmin = as.numeric( sub("\\((.+),.*", "\\1", x)),
              xmax = as.numeric( sub("[^,]*,([^]]*)\\]", "\\1", x)),
              ymin = as.numeric( sub("\\((.+),.*", "\\1", y)),
              ymax = as.numeric( sub("[^,]*,([^]]*)\\]", "\\1", y)),
              xint = as.numeric(x),
              yint = as.numeric(y))

# then, visualize
ggplot(df2, aes(xint, yint, xmin = xmin, ymin = ymin, xmax = xmax, ymax = ymax, fill = Mean)) +
  geom_tile(stat = "identity")

ggplot(df2, aes(xint, yint, xmin = xmin, ymin = ymin, xmax = xmax, ymax = ymax, fill = Var)) +
  geom_tile(stat = "identity")

enter image description here

enter image description here