如何在绘图边缘绘制以 R 为底的直方图

How to plot histograms in base R in the margin of a plot

我想将以 R 为底的直方图添加到图的边缘,我尝试了很多方法,并使用点和线段来绘制从直方图计算的值。挑战在于绘制数据后,必须手动设置条形的宽度才能显示像边距图这样的直方图。

# Inspired from
# https://github.com/ChrKoenig/R_marginal_plot/blob/master/marginal_plot.R
par(mfrow = c(1,2), mar =c(4,4,3,3), cex = 1.4)
set.seed(1234)
n = 250
x.1 = rnorm(n, mean = 15, sd = 5)
y.1 = rnorm(n, mean = 5, sd = 2)

x.2 = rnorm(n, mean = 15, sd = 1)
y.2 = rnorm(n, mean = 5, sd = .5)
x = x.1
y = y.1
moreargs$xlim[1] <- range(c(-3,x.1,x.2, max(x.1,x.2)+5))[1]
moreargs$xlim[2] <- range(c(-3,x.1,x.2, max(x.1,x.2)+5))[2]
moreargs$ylim[1] <- range(c(y.1,y.2,max(y.1,y.2)+5))[1]
moreargs$ylim[2] <- range(c(y.1,y.2,max(y.1,y.2)+5))[2]
require(scales)

# plotting
data = data.frame(x = as.numeric(x), y = as.numeric(y))
group_colors = "black"


ifelse(test = !is.null(data$group), 
       yes = data_split <- split(data, data$group), 
       no = data_split <- list(data))
orig_par = par(no.readonly = T)
par(mar = c(0.25,5,1,0))
layout(matrix(1:4, nrow = 2, byrow = T), widths = c(10,3), heights = c(3,10))

histval = hist(x = data_split[[1]]$x, plot = FALSE)

# upper density plot
plot(NULL, type = "n", 
     ylab = "Counts",
     xlim = moreargs$xlim,
     ylim = c(0, max(histval$counts)),
     main = NA, axes = F)
points(histval$mids,histval$counts, type= "h", lwd = 33, lend="butt", col = 'gray60')
# points(histval$mids,histval$counts-1, type= "h", lwd = 30, lend="butt", col = 'gray80')
axis(2, tck = 0.04)

# (add an empty plot in the corner)
par(mar = c(0.25,0.25,0,0))
plot.new()

# main plot
par(mar = c(4,5,0,0))
plot(y.1~x.1, 
     ylim = moreargs$ylim, 
     xlim = moreargs$xlim,
     pch = 19, col = scales::alpha("black",.8), ylab = "Y",xlab = "X")
axis(3, labels = F, tck = 0.01)
axis(4, labels = F, tck = 0.01)
box()

# right density plot
par(mar = c(4,0.25,0,1))
histval.y = hist(x = data_split[[1]]$y, plot = FALSE)
plot(NULL, type = "n", 
     xlab = "Counts",
     xlim = c(0, max(histval$counts)),
     ylim = moreargs$ylim,
     main = NA, axes = F)

segments(x0 = 0,x1 = histval.y$counts,
         y0 = histval.y$mids,y1 = histval.y$mids,
         lwd = rep(c(46,2), each = length(histval.y$counts)), col = "gray60", lend="butt")
axis(1,tck=0.04)
par(orig_par)

有没有办法在地块的边缘制作以 R 为底的直方图?

  1. 利用layout,可以设置一个space为0,这样就不需要情节了,它是空的space。

  2. hist不支持水平模式,建议(需要) to use barplot are constrained in that one cannot fix where on the x-axis the bars are positioned. Yet another workaround:因为barplotrect的包装器,我们可以自己写。

此函数模仿 barplot一些,但允许我们设置 条形图所在的位置。这是为了确保共享轴可以是相同的尺寸。

barplot2 <- function(xs, ys, ..., space = 0, horiz = FALSE) {
  mids <- diff(xs) / 2
  mids <- c(mids[1], mids) - space/2
  if (horiz) {
    rect(0, xs - mids, ys, xs + mids, ...)
  } else {
    rect(xs - mids, 0, xs + mids, ys, ...)
  }
}

在那里添加 plot 应该也是可行的,但是需要明确所有参数,或者确定 ... 中的哪个参数转到 plot 并转到 rect。我暂时回避这个讨论,直接给自己打电话plot

layout(
  matrix(c(2,0,
           1,3), byrow=TRUE, nrow=2),
  widths = c(4,1), heights = c(1,4)
)
# main plot
par(mar = c(4, 5, 0, 0) + 0.1)
plot(y ~ x, data = data, pch = 16)
usr <- par("usr")
# top margin
par(mar = c(0, 5, 0, 0) + 0.1)
hx <- hist(data$x, plot = FALSE)
hy <- hist(data$y, plot = FALSE)
plot(NA, type = "n", xlim = usr[1:2], ylim = c(0, max(c(hx$counts, hy$counts))),
     xaxs = "i", yaxs = "i", xaxt = "n", ylab = "Counts", frame = FALSE)
barplot2(hx$mids, hx$counts, space = 0, horiz = FALSE, col = "gray")
# right margin
par(mar = c(4, 0, 0, 0) + 0.1)
plot(NA, type = "n", xlim = c(0, max(c(hx$counts, hy$counts))), ylim = usr[3:4],
     xaxs = "i", yaxs = "i", yaxt = "n", xlab = "Counts", frame = FALSE)
barplot2(hy$mids, hy$counts, space = 0, horiz = TRUE, col = "gray")