【问题标题】:Overlay two plots on top of each other将两个图叠加在一起
【发布时间】:2020-07-11 11:40:50
【问题描述】:

我正在处理两个地块。

情节 1:茎叶图

data("mtcars")
x <- mtcars$wt
stem(x)


 1 | 5689
 2 | 123
 2 | 56889
 3 | 22224444
 3 | 55667888
 4 | 1
 4 | 
 5 | 334

图 2:这些数据点的 Z 值

 mu = mean(x)
 sdev <- sd(x)

 y <- (1/(sdev * sqrt(2*pi))) * exp(-((x-mu)^2)/(2*sdev^2))
 plot(x,y, pch = 8)

我的目标是将这两个图叠加在一起。预期的情节看起来像这样。非常感谢任何建议或帮助。谢谢。

【问题讨论】:

    标签: r ggplot2 plot


    【解决方案1】:

    不幸的是,stem 函数没有返回任何内容,这让生活变得困难。另外,代码是用 C 语言编写的,可以在here 获得。我尝试使用简单的 R 函数复制 stem 函数,这当然与 C 代码不匹配,但它适用于此示例数据集。我当然没有包含任何 stem 的论点(比例、宽度、原子)。

    data(mtcars)
    
    x <- mtcars$wt
    stem(x) # you can see the result from the question.
    
    mu = mean(x)
    sdev <- sd(x)
    
    y <- (1/(sdev * sqrt(2*pi))) * exp(-((x-mu)^2)/(2*sdev^2))
    

    这是你的密度图:

    par(mar=c(2,1,1,1))
    plot(x, y, pch = 8, xaxt="n", yaxt="n", ylab="", col="grey)
    

    现在我们需要从头开始重新发明stem 函数。我首先使用hist 函数定义“最佳”断点,我猜测类似于stem 所做的。

    h <- hist(round(x,1), right=FALSE, plot=F)
    bin <- h$breaks; bin
    #[1] 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5
    

    然后我使用 cut 将 x 值分配到正确的 bin 中。

    xgr <- sort(cut(round(x,1), breaks = bin, right=FALSE, labels = FALSE, include = TRUE))
    

    然后我使用 data.table 中的rowid 函数来定义 y 轴值,除以它的长度以获得密度,以便两个图使用相同的 y 轴系统。

    library(data.table)
    y <- rowid(xgr)/length(xgr); y
    

    要绘制的实际字符 (pch) 来自小数点后的第一位。

    pch <- as.character(round(10*(round(sort(x),1) %% 1))); pch
    # [1] "5" "6" "8" "9" "1" "2" "3" "5" "6" "8" "8" "9" "1" "2" "2" "2"
    #[17] "4" "4" "4" "4" "5" "5" "6" "6" "7" "8" "8" "8" "1" "2" "3" "4"
    

    最后是 x 轴的“at”。

    at <- seq(min(x), max(x), length.out=length(bin)-1)
    x <- rep(at, h$counts)
        
    points(x, y, pch = pch, col="red")
    axis(side=1, at=at, labels=trunc(bin[-length(bin)]), tck=-0.02, mgp=c(1,0.3,0), col="red", col.axis="red")
    

    一个显着的区别是stem 不像我在这里所做的那样使用round。它似乎在第 96 行和第 103 行使用了floor(x+0.5),这解释了细微的差异。另一个问题是它需要调整以使其更加健壮。

    例如,将x 替换为mtcars$drat 需要将scale 参数更改为0.5。

    x <- mtcars$drat
    stem(x, scale=0.5)
    
      The decimal point is at the |
    
      2 | 889
      3 | 0111112222
      3 | 567778999999
      4 | 111224
      4 | 9
    

    【讨论】:

    • 谢谢爱德华,这很有趣,我现在正在研究你的例子
    【解决方案2】:

    stem() 实际上不会产生典型的图形图(我也不能保存或轻松地从其结构中提取信息),所以我不确定如何用图形图覆盖stem() 输出,例如由plot()ggplot() 制作的。

    但是,将两个绘图信息放到同一个绘图上的另一种方法是使用 ggplot()annotate() 来显示绘图 1 的 stem() 信息和 geom_point() 来显示绘图 2 的散点图。

    stem(x) # copy and paste this stem-and-leaf plot to a variable
    sal <- c("1 | 5689", "2 | 123", "2 | 56889", "3 | 22224444", "3 | 55667888", "4 | 1", "4 | ", "5 | 334")
    
    # make sal into a single string, collapse using new lines ("\n")
    sal2 <- paste(sal, collapse="\n\n") # here I am using two new lines to widen the line spacing
    sal2 <- gsub("\\|" ," ", sal2) # change the vertical bar ("|") to a space if you want to later replace it with geom_segment() (optional depending on how you like your aesthetics)
    
    sal_x_position <- min(x) + (max(x) - min(x))/2 # the center of x-axis will be the center of the stem-and-leaf
        
    df <- data.frame(x, y)
    
    ggplot(df, aes(x, y)) + 
      # plot Plot 1
      annotate("text", x = sal_x_position, y = 0, label = sal2, angle = 90, hjust = 0, col = "red") + 
      geom_segment(aes(x = 2, y = 0.015, xend = 5, yend = 0.015), col = "red") + # add a line between the stems and leaves (caveat: must choose custom coordinates for its location)
      # plot Plot 2
      geom_point(pch = 8) + 
      geom_line() + 
      # customize other plot aesthetics
      theme_bw() + 
      theme(panel.grid = element_blank())
    

    请注意,如果您想更好地控制每个文本在绘图上的映射位置,也可以使用 sal 而不是 sal2。您只需使用多层 annotate() 并指定每个位置(请参阅我在编辑历史中的原始帖子以获取示例)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-05
      • 2020-07-16
      • 2021-12-13
      • 2016-04-01
      • 1970-01-01
      相关资源
      最近更新 更多