首页 文章

绘制2 y轴,左侧为y轴,右侧为y轴

提问于
浏览
170

我需要绘制一个显示计数的条形图和一个在一个图表中显示速率的折线图,我可以分别做两个,但是当我把它们放在一起时,我的第一层的比例(即 geom_bar )重叠了第二层(即 geom_line ) .

我可以将 geom_line 的轴向右移动吗?

13 回答

  • 0

    有时客户想要两个y尺度 . 给他们“有缺陷”的演讲往往毫无意义 . 但我确实喜欢ggplot2坚持以正确的方式做事 . 我确信ggplot实际上是教育普通用户正确的可视化技术 .

    也许你可以使用faceting和scale来比较两个数据系列? - 例如看这里:https://github.com/hadley/ggplot2/wiki/Align-two-plots-on-a-page

  • 1

    这在ggplot2中是不可能的,因为我认为具有单独y尺度的图(不是彼此变换的y尺度)从根本上是有缺陷的 . 一些问题:

    • 不可逆:如果绘图空间上有一个点,则无法将其唯一映射回数据空间中的某个点 .

    • 与其他选项相比,它们相对难以正确阅读 . 有关详细信息,请参阅Petra Isenberg,Anastasia Bezerianos,Pierre Dragicevic和Jean-Daniel Fekete的A Study on Dual-Scale Data Charts .

    • 它们很容易操纵误导:没有独特的方法来指定轴的相对比例,使它们处于操作状态 . Junkcharts博客中的两个例子:onetwo

    • 它们是任意的:为什么只有2个刻度,而不是3个,4个或10个?

    您也可以阅读Stephen Few关于Dual-Scaled Axes in Graphs Are They Ever the Best Solution?主题的冗长讨论 .

  • 124

    从ggplot2 2.2.0开始,您可以添加这样的辅助轴(取自ggplot2 2.2.0 announcement):

    ggplot(mpg, aes(displ, hwy)) + 
      geom_point() + 
      scale_y_continuous(
        "mpg (US)", 
        sec.axis = sec_axis(~ . * 1.20, name = "mpg (UK)")
      )
    

    enter image description here

  • 0

    大约3年前,Kohske提供了解决这一挑战的技术支柱[KOHSKE] . 关于其解决方案的主题和技术已经在Stackoverflow上的几个实例中进行了讨论[ID:18989001,29235405,21026598] . 因此,我将仅使用上述解决方案提供特定的变体和一些解释性演练 .

    让我们假设我们在组G1中确实存在一些数据y1,其中组G2中的一些数据y2以某种方式相关,例如,范围/比例变换或添加一些噪音 . 因此,人们希望将数据绘制在一个图上,左边是y1,右边是y2 .

    df <- data.frame(item=LETTERS[1:n],  y1=c(-0.8684, 4.2242, -0.3181, 0.5797, -0.4875), y2=c(-5.719, 205.184, 4.781, 41.952, 9.911 )) # made up!
    
    > df
      item      y1         y2
    1    A -0.8684 -19.154567
    2    B  4.2242 219.092499
    3    C -0.3181  18.849686
    4    D  0.5797  46.945161
    5    E -0.4875  -4.721973
    

    如果我们现在将数据与类似的东西一起绘制

    ggplot(data=df, aes(label=item)) +
      theme_bw() + 
      geom_segment(aes(x='G1', xend='G2', y=y1, yend=y2), color='grey')+
      geom_text(aes(x='G1', y=y1), color='blue') +
      geom_text(aes(x='G2', y=y2), color='red') +
      theme(legend.position='none', panel.grid=element_blank())
    

    它没有很好地对齐,因为较小的规模y1明显地被更大规模的y2折叠 .

    The trick here to meet the challenge is to techncially plot both data sets against the first scale y1 but report the second against a secondary axis with labels showing the original scale y2.

    因此,我们构建了第一个辅助函数CalcFudgeAxis,它计算并收集要显示的新轴的特征 . 该函数可以修改为ayones喜欢(这个只是将y2映射到y1的范围) .

    CalcFudgeAxis = function( y1, y2=y1) {
      Cast2To1 = function(x) ((ylim1[2]-ylim1[1])/(ylim2[2]-ylim2[1])*x) # x gets mapped to range of ylim2
      ylim1 <- c(min(y1),max(y1))
      ylim2 <- c(min(y2),max(y2))    
      yf <- Cast2To1(y2)
      labelsyf <- pretty(y2)  
      return(list(
        yf=yf,
        labels=labelsyf,
        breaks=Cast2To1(labelsyf)
      ))
    }
    

    什么产生一些:

    > FudgeAxis <- CalcFudgeAxis( df$y1, df$y2 )
    
    > FudgeAxis
    $yf
    [1] -0.4094344  4.6831656  0.4029175  1.0034664 -0.1009335
    
    $labels
    [1] -50   0  50 100 150 200 250
    
    $breaks
    [1] -1.068764  0.000000  1.068764  2.137529  3.206293  4.275058  5.343822
    
    
    > cbind(df, FudgeAxis$yf)
      item      y1         y2 FudgeAxis$yf
    1    A -0.8684 -19.154567   -0.4094344
    2    B  4.2242 219.092499    4.6831656
    3    C -0.3181  18.849686    0.4029175
    4    D  0.5797  46.945161    1.0034664
    5    E -0.4875  -4.721973   -0.1009335
    

    现在我在第二个辅助函数PlotWithFudgeAxis(我们在其中抛出新轴的ggplot对象和辅助对象)中包含了Kohske的解决方案:

    library(gtable)
    library(grid)
    
    PlotWithFudgeAxis = function( plot1, FudgeAxis) {
      # based on: https://rpubs.com/kohske/dual_axis_in_ggplot2
      plot2 <- plot1 + with(FudgeAxis, scale_y_continuous( breaks=breaks, labels=labels))
    
      #extract gtable
      g1<-ggplot_gtable(ggplot_build(plot1))
      g2<-ggplot_gtable(ggplot_build(plot2))
    
      #overlap the panel of the 2nd plot on that of the 1st plot
      pp<-c(subset(g1$layout, name=="panel", se=t:r))
      g<-gtable_add_grob(g1, g2$grobs[[which(g2$layout$name=="panel")]], pp$t, pp$l, pp$b,pp$l)
    
      ia <- which(g2$layout$name == "axis-l")
      ga <- g2$grobs[[ia]]
      ax <- ga$children[[2]]
      ax$widths <- rev(ax$widths)
      ax$grobs <- rev(ax$grobs)
      ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm")
      g <- gtable_add_cols(g, g2$widths[g2$layout[ia, ]$l], length(g$widths) - 1)
      g <- gtable_add_grob(g, ax, pp$t, length(g$widths) - 1, pp$b)
    
      grid.draw(g)
    }
    

    现在所有人都可以放在一起: Below code shows, how the proposed solution could be used in a day-to-day environment . 情节调用现在不再绘制原始数据y2,而是克隆版本yf(保存在预先计算的辅助对象FudgeAxis内),其运行y1的比例 . 然后使用Kohske的辅助函数PlotWithFudgeAxis操作原始的ggplot对象,以添加第二个轴,保留y2的比例 . 它也描绘了操纵的情节 .

    FudgeAxis <- CalcFudgeAxis( df$y1, df$y2 )
    
    tmpPlot <- ggplot(data=df, aes(label=item)) +
          theme_bw() + 
          geom_segment(aes(x='G1', xend='G2', y=y1, yend=FudgeAxis$yf), color='grey')+
          geom_text(aes(x='G1', y=y1), color='blue') +
          geom_text(aes(x='G2', y=FudgeAxis$yf), color='red') +
          theme(legend.position='none', panel.grid=element_blank())
    
    PlotWithFudgeAxis(tmpPlot, FudgeAxis)
    

    This now plots as desired with two axis, y1 on the left and y2 on the right

    2 axes

    上面的解决方案是,直截了当,一个有限的摇摇欲坠的黑客 . 当它与ggplot内核一起使用时,它会抛出一些警告,我们交换事后的比例等等 . 它必须小心处理,并可能在另一个设置中产生一些不希望的行为 . 同样,可能需要使用辅助函数来调整以获得所需的布局 . 图例的位置是一个问题(它将放置在面板和新轴之间;这就是我下垂的原因) . 2轴的缩放/对齐也有点挑战性:当两个刻度包含“0”时,上面的代码很好地工作,否则一个轴会移位 . 所以肯定有一些改进的机会......

    如果想要保存pic,必须将呼叫包装到设备打开/关闭中:

    png(...)
    PlotWithFudgeAxis(tmpPlot, FudgeAxis)
    dev.off()
    
  • 10

    采取上述答案和一些微调(以及任何它的 Value ),这是一种通过 sec_axis 实现两个量表的方法:

    假设一个简单的(纯虚构的)数据集 dt :五天,它跟踪的数量中断VS 生产环境 力:

    when numinter prod
    1 2018-03-20        1 0.95
    2 2018-03-21        5 0.50
    3 2018-03-23        4 0.70
    4 2018-03-24        3 0.75
    5 2018-03-25        4 0.60
    

    (两列的范围相差约5倍) .

    以下代码将绘制它们用完整个y轴的两个系列:

    ggplot() + 
      geom_bar(mapping = aes(x = dt$when, y = dt$numinter), stat = "identity", fill = "grey") +
      geom_line(mapping = aes(x = dt$when, y = dt$prod*5), size = 2, color = "blue") + 
      scale_x_date(name = "Day", labels = NULL) +
      scale_y_continuous(name = "Interruptions/day", 
        sec.axis = sec_axis(~./5, name = "Productivity % of best", 
          labels = function(b) { paste0(round(b * 100, 0), "%")})) + 
      theme(
          axis.title.y = element_text(color = "grey"),
          axis.title.y.right = element_text(color = "blue"))
    

    这是结果(上面的代码有些颜色调整):

    two scales in one ggplot2

    要点(除了在指定y_scale时使用 sec_axismultiply ,在指定系列时每个值为第2个数据系列为5 . 为了在sec_axis定义中获得标签,它需要 dividing by 5(和格式化) . 因此,上面代码中的一个关键部分实际上是geom_line中的 *5 和sec_axis中的 ~./5 (将当前值 . 除以5的公式) .

    相比之下(我不想在这里判断方法),这是两个图表在彼此之上的样子:

    two charts above one another

    你可以自己判断哪一个更能传达信息(“不要扰乱工作中的人!”) . 猜猜这是一个公平的决定方式 .

    两个图像的完整代码(上面是's not really more than what',只是完成并准备好运行)在这里:https://gist.github.com/sebastianrothbucher/de847063f32fdff02c83b75f59c36a7d这里有更详细的解释:https://sebastianrothbucher.github.io/datascience/r/visualization/ggplot/2018/03/24/two-scales-ggplot-r.html

  • 1

    下面的文章帮助我将ggplot2生成的两个图组合在一行上:

    Multiple graphs on one page (ggplot2) by Cookbook for R

    以下是这种情况下代码的外观:

    p1 <- 
      ggplot() + aes(mns)+ geom_histogram(aes(y=..density..), binwidth=0.01, colour="black", fill="white") + geom_vline(aes(xintercept=mean(mns, na.rm=T)), color="red", linetype="dashed", size=1) +  geom_density(alpha=.2)
    
    p2 <- 
      ggplot() + aes(mns)+ geom_histogram( binwidth=0.01, colour="black", fill="white") + geom_vline(aes(xintercept=mean(mns, na.rm=T)), color="red", linetype="dashed", size=1)  
    
    multiplot(p1,p2,cols=2)
    
  • 1

    对我来说,棘手的部分是找出两个轴之间的转换函数 . 我使用了myCurveFit .

    > dput(combined_80_8192 %>% filter (time > 270, time < 280))
    structure(list(run = c(268L, 268L, 268L, 268L, 268L, 268L, 268L, 
    268L, 268L, 268L, 263L, 263L, 263L, 263L, 263L, 263L, 263L, 263L, 
    263L, 263L, 269L, 269L, 269L, 269L, 269L, 269L, 269L, 269L, 269L, 
    269L, 261L, 261L, 261L, 261L, 261L, 261L, 261L, 261L, 261L, 261L, 
    267L, 267L, 267L, 267L, 267L, 267L, 267L, 267L, 267L, 267L, 265L, 
    265L, 265L, 265L, 265L, 265L, 265L, 265L, 265L, 265L, 266L, 266L, 
    266L, 266L, 266L, 266L, 266L, 266L, 266L, 266L, 262L, 262L, 262L, 
    262L, 262L, 262L, 262L, 262L, 262L, 262L, 264L, 264L, 264L, 264L, 
    264L, 264L, 264L, 264L, 264L, 264L, 260L, 260L, 260L, 260L, 260L, 
    260L, 260L, 260L, 260L, 260L), repetition = c(8L, 8L, 8L, 8L, 
    8L, 8L, 8L, 8L, 8L, 8L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
    9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 5L, 5L, 
    5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 
    6L, 6L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
    ), module = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "scenario.node[0].nicVLCTail.phyVLC", class = "factor"), 
        configname = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
        1L, 1L), .Label = "Road-Vlc", class = "factor"), packetByteLength = c(8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 
        8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L, 8192L
        ), numVehicles = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
        2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
        2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
        2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
        2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
        2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
        2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L
        ), dDistance = c(80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 
        80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 
        80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 
        80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 
        80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 
        80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 
        80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 
        80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 
        80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L), time = c(270.166006903445, 
        271.173853699836, 272.175873251122, 273.177524313334, 274.182946177105, 
        275.188959464989, 276.189675339937, 277.198250244799, 278.204619457189, 
        279.212562800009, 270.164199199177, 271.168527215152, 272.173072994958, 
        273.179210429715, 274.184351047337, 275.18980754378, 276.194816792995, 
        277.198598277809, 278.202398083519, 279.210634593917, 270.210674322891, 
        271.212395107473, 272.218871923292, 273.219060500457, 274.220486359614, 
        275.22401452372, 276.229646658839, 277.231060448138, 278.240407241942, 
        279.2437126347, 270.283554249858, 271.293168593832, 272.298574288769, 
        273.304413221348, 274.306272082517, 275.309023049011, 276.317805897347, 
        277.324403550028, 278.332855848701, 279.334046374594, 270.118608539613, 
        271.127947700074, 272.133887145863, 273.135726000491, 274.135994529981, 
        275.136563912708, 276.140120735361, 277.144298344151, 278.146885137621, 
        279.147552358659, 270.206015567272, 271.214618077209, 272.216566814903, 
        273.225435592582, 274.234014573683, 275.242949179958, 276.248417809711, 
        277.248800670023, 278.249750333404, 279.252926560188, 270.217182684494, 
        271.218357511397, 272.224698488895, 273.231112784327, 274.238740508457, 
        275.242715184122, 276.249053562718, 277.250325509798, 278.258488063493, 
        279.261141590137, 270.282904173953, 271.284689544638, 272.294220723234, 
        273.299749415592, 274.30628880553, 275.312075103126, 276.31579134717, 
        277.321905523606, 278.326305136748, 279.333056502253, 270.258991527456, 
        271.260224091407, 272.270076810133, 273.27052037648, 274.274119348094, 
        275.280808254502, 276.286353887245, 277.287064312339, 278.294444793276, 
        279.296772014594, 270.333066283904, 271.33877455992, 272.345842319903, 
        273.350858180493, 274.353972278505, 275.360454510107, 276.365088896161, 
        277.369166956941, 278.372571708911, 279.38017503079), distanceToTx = c(80.255266401689, 
        80.156059067023, 79.98823695539, 79.826647129071, 79.76678667135, 
        79.788239825292, 79.734539327997, 79.74766421514, 79.801243848241, 
        79.765920888341, 80.255266401689, 80.15850240049, 79.98823695539, 
        79.826647129071, 79.76678667135, 79.788239825292, 79.735078924078, 
        79.74766421514, 79.801243848241, 79.764622734914, 80.251248121732, 
        80.146436869316, 79.984682320466, 79.82292012342, 79.761908518748, 
        79.796988776281, 79.736920997657, 79.745038376718, 79.802638836686, 
        79.770029970452, 80.243475525691, 80.127918207499, 79.978303140866, 
        79.816259117883, 79.749322030693, 79.809916018889, 79.744456560867, 
        79.738655068783, 79.788697533211, 79.784288359619, 80.260412958482, 
        80.168426829066, 79.992034911214, 79.830845773284, 79.7756751763, 
        79.778156038931, 79.732399593756, 79.752769548846, 79.799967731078, 
        79.757585110481, 80.251248121732, 80.146436869316, 79.984682320466, 
        79.822062073459, 79.75884601899, 79.801590491435, 79.738335109094, 
        79.74347007248, 79.803215965043, 79.771471198955, 80.250257298678, 
        80.146436869316, 79.983831684476, 79.822062073459, 79.75884601899, 
        79.801590491435, 79.738335109094, 79.74347007248, 79.803849157574, 
        79.771471198955, 80.243475525691, 80.130180105198, 79.978303140866, 
        79.816881283718, 79.749322030693, 79.80984572883, 79.744456560867, 
        79.738655068783, 79.790548644175, 79.784288359619, 80.246349000313, 
        80.137056554491, 79.980581246037, 79.818924707937, 79.753176142361, 
        79.808777040341, 79.741609845588, 79.740770913572, 79.796316397253, 
        79.777593733292, 80.238796415443, 80.119021911134, 79.974810568944, 
        79.814065350562, 79.743657315504, 79.810146783217, 79.749945098869, 
        79.737122584544, 79.781650522348, 79.791554933936), headerNoError = c(0.99999999989702, 
        0.9999999999981, 0.99999999999946, 0.9999999928026, 0.99999873265475, 
        0.77080141574964, 0.99007491438593, 0.99994396605059, 0.45588747062284, 
        0.93484381262491, 0.99999999989702, 0.99999999999816, 0.99999999999946, 
        0.9999999928026, 0.99999873265475, 0.77080141574964, 0.99008458785106, 
        0.99994396605059, 0.45588747062284, 0.93480223051707, 0.99999999989735, 
        0.99999999999789, 0.99999999999946, 0.99999999287551, 0.99999876302649, 
        0.46903147501117, 0.98835168988253, 0.99994427085086, 0.45235035271542, 
        0.93496741877335, 0.99999999989803, 0.99999999999781, 0.99999999999948, 
        0.99999999318224, 0.99994254156311, 0.46891362282273, 0.93382613917348, 
        0.99994594904099, 0.93002915596843, 0.93569767251247, 0.99999999989658, 
        0.99999999998074, 0.99999999999946, 0.99999999272802, 0.99999871586781, 
        0.76935240919896, 0.99002587758346, 0.99999881589732, 0.46179415706093, 
        0.93417422376389, 0.99999999989735, 0.99999999999789, 0.99999999999946, 
        0.99999999289347, 0.99999876940486, 0.46930769326427, 0.98837353639905, 
        0.99994447154714, 0.16313586712094, 0.93500824170148, 0.99999999989744, 
        0.99999999999789, 0.99999999999946, 0.99999999289347, 0.99999876940486, 
        0.46930769326427, 0.98837353639905, 0.99994447154714, 0.16330039178981, 
        0.93500824170148, 0.99999999989803, 0.99999999999781, 0.99999999999948, 
        0.99999999316541, 0.99994254156311, 0.46794586553266, 0.93382613917348, 
        0.99994594904099, 0.9303627789484, 0.93569767251247, 0.99999999989778, 
        0.9999999999978, 0.99999999999948, 0.99999999311433, 0.99999878195152, 
        0.47101897739483, 0.93368891853679, 0.99994556595217, 0.7571113417265, 
        0.93553999975802, 0.99999999998191, 0.99999999999784, 0.99999999999971, 
        0.99999891129658, 0.99994309267792, 0.46510628979591, 0.93442584181035, 
        0.99894450514543, 0.99890078483692, 0.76933812306423), receivedPower_dbm = c(-93.023492290586, 
        -92.388378035287, -92.205716340607, -93.816400586752, -95.023489422885, 
        -100.86308557253, -98.464763536915, -96.175707680373, -102.06189538385, 
        -99.716653422746, -93.023492290586, -92.384760627397, -92.205716340607, 
        -93.816400586752, -95.023489422885, -100.86308557253, -98.464201120719, 
        -96.175707680373, -102.06189538385, -99.717150021506, -93.022927803442, 
        -92.404017215549, -92.204561341714, -93.814319484729, -95.016990717792, 
        -102.01669022332, -98.558088145955, -96.173817001483, -102.07406915124, 
        -99.71517574876, -93.021813165972, -92.409586309743, -92.20229160243, 
        -93.805335867418, -96.184419849593, -102.01709540787, -99.728735187547, 
        -96.163233028048, -99.772547164798, -99.706399753853, -93.024204617071, 
        -92.745813384859, -92.206884754512, -93.818508150122, -95.027018807793, 
        -100.87000577258, -98.467607232407, -95.005311380324, -102.04157607608, 
        -99.724619517, -93.022927803442, -92.404017215549, -92.204561341714, 
        -93.813803344588, -95.015606885523, -102.0157405687, -98.556982278361, 
        -96.172566862738, -103.21871579865, -99.714687230796, -93.022787428238, 
        -92.404017215549, -92.204274688493, -93.813803344588, -95.015606885523, 
        -102.0157405687, -98.556982278361, -96.172566862738, -103.21784988098, 
        -99.714687230796, -93.021813165972, -92.409950613665, -92.20229160243, 
        -93.805838770576, -96.184419849593, -102.02042267497, -99.728735187547, 
        -96.163233028048, -99.768774335378, -99.706399753853, -93.022228914406, 
        -92.411048503835, -92.203136463155, -93.807357409082, -95.012865008237, 
        -102.00985717796, -99.730352912911, -96.165675535906, -100.92744056572, 
        -99.708301333236, -92.735781110993, -92.408137395049, -92.119533319039, 
        -94.982938427575, -96.181073124017, -102.03018610927, -99.721633629806, 
        -97.32940323644, -97.347613268692, -100.87007386786), snr = c(49.848348091678, 
        57.698190927109, 60.17669971462, 41.529809724535, 31.452202106925, 
        8.1976890851341, 14.240447804094, 24.122884195464, 6.2202875499406, 
        10.674183333671, 49.848348091678, 57.746270018264, 60.17669971462, 
        41.529809724535, 31.452202106925, 8.1976890851341, 14.242292077376, 
        24.122884195464, 6.2202875499406, 10.672962852322, 49.854827699773, 
        57.49079026127, 60.192705735317, 41.549715223147, 31.499301851462, 
        6.2853718719014, 13.937702343688, 24.133388256416, 6.2028757927148, 
        10.677815810561, 49.867624820879, 57.417115267867, 60.224172277442, 
        41.635752021705, 24.074540962859, 6.2847854917092, 10.644529778044, 
        24.19227425387, 10.537686730745, 10.699414795917, 49.84017267426, 
        53.139646558768, 60.160512118809, 41.509660845114, 31.42665220053, 
        8.1846370024428, 14.231126423354, 31.584125885363, 6.2494585568733, 
        10.654622041348, 49.854827699773, 57.49079026127, 60.192705735317, 
        41.55465351989, 31.509340361646, 6.2867464196657, 13.941251828322, 
        24.140336174865, 4.765718874642, 10.679016976694, 49.856439162736, 
        57.49079026127, 60.196678846453, 41.55465351989, 31.509340361646, 
        6.2867464196657, 13.941251828322, 24.140336174865, 4.7666691818074, 
        10.679016976694, 49.867624820879, 57.412299088098, 60.224172277442, 
        41.630930975211, 24.074540962859, 6.279972363168, 10.644529778044, 
        24.19227425387, 10.546845071479, 10.699414795917, 49.862851240855, 
        57.397787176282, 60.212457625018, 41.61637603957, 31.529239767749, 
        6.2952688513108, 10.640565481982, 24.178672145334, 8.0771089950663, 
        10.694731030907, 53.262541905639, 57.43627424514, 61.382796189332, 
        31.747253311549, 24.093100244121, 6.2658701281075, 10.661949889074, 
        18.495227442305, 18.417839037171, 8.1845086722809), frameId = c(15051, 
        15106, 15165, 15220, 15279, 15330, 15385, 15452, 15511, 15566, 
        15019, 15074, 15129, 15184, 15239, 15298, 15353, 15412, 15471, 
        15526, 14947, 14994, 15057, 15112, 15171, 15226, 15281, 15332, 
        15391, 15442, 14971, 15030, 15085, 15144, 15203, 15262, 15321, 
        15380, 15435, 15490, 14915, 14978, 15033, 15092, 15147, 15198, 
        15257, 15312, 15371, 15430, 14975, 15034, 15089, 15140, 15195, 
        15254, 15313, 15368, 15427, 15478, 14987, 15046, 15105, 15160, 
        15215, 15274, 15329, 15384, 15447, 15506, 14943, 15002, 15061, 
        15116, 15171, 15230, 15285, 15344, 15399, 15454, 14971, 15026, 
        15081, 15136, 15195, 15258, 15313, 15368, 15423, 15478, 15039, 
        15094, 15149, 15204, 15263, 15314, 15369, 15428, 15487, 15546
        ), packetOkSinr = c(0.99999999314881, 0.9999999998736, 0.99999999996428, 
        0.99999952114066, 0.99991568416005, 3.00628034688444e-08, 
        0.51497487795954, 0.99627877136019, 0, 0.011303253101957, 
        0.99999999314881, 0.99999999987726, 0.99999999996428, 0.99999952114066, 
        0.99991568416005, 3.00628034688444e-08, 0.51530974419663, 
        0.99627877136019, 0, 0.011269851265775, 0.9999999931708, 
        0.99999999985986, 0.99999999996428, 0.99999952599145, 0.99991770469509, 
        0, 0.45861812482641, 0.99629897628155, 0, 0.011403119534097, 
        0.99999999321568, 0.99999999985437, 0.99999999996519, 0.99999954639936, 
        0.99618434878558, 0, 0.010513119213425, 0.99641022914441, 
        0.00801687746446111, 0.012011103529927, 0.9999999931195, 
        0.99999999871861, 0.99999999996428, 0.99999951617905, 0.99991456738049, 
        2.6525298291169e-08, 0.51328066587104, 0.9999212220316, 0, 
        0.010777054258914, 0.9999999931708, 0.99999999985986, 0.99999999996428, 
        0.99999952718674, 0.99991812902805, 0, 0.45929307038653, 
        0.99631228046814, 0, 0.011436292559188, 0.99999999317629, 
        0.99999999985986, 0.99999999996428, 0.99999952718674, 0.99991812902805, 
        0, 0.45929307038653, 0.99631228046814, 0, 0.011436292559188, 
        0.99999999321568, 0.99999999985437, 0.99999999996519, 0.99999954527918, 
        0.99618434878558, 0, 0.010513119213425, 0.99641022914441, 
        0.00821047996950475, 0.012011103529927, 0.99999999319919, 
        0.99999999985345, 0.99999999996519, 0.99999954188106, 0.99991896371849, 
        0, 0.010410830482692, 0.996384831822, 9.12484388049251e-09, 
        0.011877185067536, 0.99999999879646, 0.9999999998562, 0.99999999998077, 
        0.99992756868677, 0.9962208785486, 0, 0.010971897073662, 
        0.93214999078663, 0.92943956665979, 2.64925478221656e-08), 
        snir = c(49.848348091678, 57.698190927109, 60.17669971462, 
        41.529809724535, 31.452202106925, 8.1976890851341, 14.240447804094, 
        24.122884195464, 6.2202875499406, 10.674183333671, 49.848348091678, 
        57.746270018264, 60.17669971462, 41.529809724535, 31.452202106925, 
        8.1976890851341, 14.242292077376, 24.122884195464, 6.2202875499406, 
        10.672962852322, 49.854827699773, 57.49079026127, 60.192705735317, 
        41.549715223147, 31.499301851462, 6.2853718719014, 13.937702343688, 
        24.133388256416, 6.2028757927148, 10.677815810561, 49.867624820879, 
        57.417115267867, 60.224172277442, 41.635752021705, 24.074540962859, 
        6.2847854917092, 10.644529778044, 24.19227425387, 10.537686730745, 
        10.699414795917, 49.84017267426, 53.139646558768, 60.160512118809, 
        41.509660845114, 31.42665220053, 8.1846370024428, 14.231126423354, 
        31.584125885363, 6.2494585568733, 10.654622041348, 49.854827699773, 
        57.49079026127, 60.192705735317, 41.55465351989, 31.509340361646, 
        6.2867464196657, 13.941251828322, 24.140336174865, 4.765718874642, 
        10.679016976694, 49.856439162736, 57.49079026127, 60.196678846453, 
        41.55465351989, 31.509340361646, 6.2867464196657, 13.941251828322, 
        24.140336174865, 4.7666691818074, 10.679016976694, 49.867624820879, 
        57.412299088098, 60.224172277442, 41.630930975211, 24.074540962859, 
        6.279972363168, 10.644529778044, 24.19227425387, 10.546845071479, 
        10.699414795917, 49.862851240855, 57.397787176282, 60.212457625018, 
        41.61637603957, 31.529239767749, 6.2952688513108, 10.640565481982, 
        24.178672145334, 8.0771089950663, 10.694731030907, 53.262541905639, 
        57.43627424514, 61.382796189332, 31.747253311549, 24.093100244121, 
        6.2658701281075, 10.661949889074, 18.495227442305, 18.417839037171, 
        8.1845086722809), ookSnirBer = c(8.8808636558081e-24, 3.2219795637026e-27, 
        2.6468895519653e-28, 3.9807779074715e-20, 1.0849324265615e-15, 
        2.5705217057696e-05, 4.7313805615763e-08, 1.8800438086075e-12, 
        0.00021005320203921, 1.9147343768384e-06, 8.8808636558081e-24, 
        3.0694773489537e-27, 2.6468895519653e-28, 3.9807779074715e-20, 
        1.0849324265615e-15, 2.5705217057696e-05, 4.7223753038869e-08, 
        1.8800438086075e-12, 0.00021005320203921, 1.9171738578051e-06, 
        8.8229427230445e-24, 3.9715925056443e-27, 2.6045198111088e-28, 
        3.9014083702734e-20, 1.0342658440386e-15, 0.00019591630514278, 
        6.4692014108683e-08, 1.8600094209271e-12, 0.0002140067535655, 
        1.9074922485477e-06, 8.7096574467175e-24, 4.2779443633862e-27, 
        2.5231916788231e-28, 3.5761615214425e-20, 1.9750692814982e-12, 
        0.0001960392878411, 1.9748966344895e-06, 1.7515881895994e-12, 
        2.2078334799411e-06, 1.8649940680806e-06, 8.954486301678e-24, 
        3.2021085732779e-25, 2.690441113724e-28, 4.0627628846548e-20, 
        1.1134484878561e-15, 2.6061691733331e-05, 4.777159157954e-08, 
        9.4891388749738e-16, 0.00020359398491544, 1.9542110660398e-06, 
        8.8229427230445e-24, 3.9715925056443e-27, 2.6045198111088e-28, 
        3.8819641115984e-20, 1.0237769828158e-15, 0.00019562832342849, 
        6.4455095380046e-08, 1.8468752030971e-12, 0.0010099091367628, 
        1.9051035165106e-06, 8.8085966897635e-24, 3.9715925056443e-27, 
        2.594108048185e-28, 3.8819641115984e-20, 1.0237769828158e-15, 
        0.00019562832342849, 6.4455095380046e-08, 1.8468752030971e-12, 
        0.0010088638355194, 1.9051035165106e-06, 8.7096574467175e-24, 
        4.2987746909572e-27, 2.5231916788231e-28, 3.593647329558e-20, 
        1.9750692814982e-12, 0.00019705170257492, 1.9748966344895e-06, 
        1.7515881895994e-12, 2.1868296425817e-06, 1.8649940680806e-06, 
        8.7517439682173e-24, 4.3621551072316e-27, 2.553168170837e-28, 
        3.6469582463164e-20, 1.0032983660212e-15, 0.00019385229409318, 
        1.9830820164805e-06, 1.7760568361323e-12, 2.919419915209e-05, 
        1.8741284335866e-06, 2.8285944348148e-25, 4.1960751547207e-27, 
        7.8468215407139e-29, 8.0407329049747e-16, 1.9380328071065e-12, 
        0.00020004849911333, 1.9393279417733e-06, 5.9354475879597e-10, 
        6.4258355913627e-10, 2.6065221215415e-05), ookSnrBer = c(8.8808636558081e-24, 
        3.2219795637026e-27, 2.6468895519653e-28, 3.9807779074715e-20, 
        1.0849324265615e-15, 2.5705217057696e-05, 4.7313805615763e-08, 
        1.8800438086075e-12, 0.00021005320203921, 1.9147343768384e-06, 
        8.8808636558081e-24, 3.0694773489537e-27, 2.6468895519653e-28, 
        3.9807779074715e-20, 1.0849324265615e-15, 2.5705217057696e-05, 
        4.7223753038869e-08, 1.8800438086075e-12, 0.00021005320203921, 
        1.9171738578051e-06, 8.8229427230445e-24, 3.9715925056443e-27, 
        2.6045198111088e-28, 3.9014083702734e-20, 1.0342658440386e-15, 
        0.00019591630514278, 6.4692014108683e-08, 1.8600094209271e-12, 
        0.0002140067535655, 1.9074922485477e-06, 8.7096574467175e-24, 
        4.2779443633862e-27, 2.5231916788231e-28, 3.5761615214425e-20, 
        1.9750692814982e-12, 0.0001960392878411, 1.9748966344895e-06, 
        1.7515881895994e-12, 2.2078334799411e-06, 1.8649940680806e-06, 
        8.954486301678e-24, 3.2021085732779e-25, 2.690441113724e-28, 
        4.0627628846548e-20, 1.1134484878561e-15, 2.6061691733331e-05, 
        4.777159157954e-08, 9.4891388749738e-16, 0.00020359398491544, 
        1.9542110660398e-06, 8.8229427230445e-24, 3.9715925056443e-27, 
        2.6045198111088e-28, 3.8819641115984e-20, 1.0237769828158e-15, 
        0.00019562832342849, 6.4455095380046e-08, 1.8468752030971e-12, 
        0.0010099091367628, 1.9051035165106e-06, 8.8085966897635e-24, 
        3.9715925056443e-27, 2.594108048185e-28, 3.8819641115984e-20, 
        1.0237769828158e-15, 0.00019562832342849, 6.4455095380046e-08, 
        1.8468752030971e-12, 0.0010088638355194, 1.9051035165106e-06, 
        8.7096574467175e-24, 4.2987746909572e-27, 2.5231916788231e-28, 
        3.593647329558e-20, 1.9750692814982e-12, 0.00019705170257492, 
        1.9748966344895e-06, 1.7515881895994e-12, 2.1868296425817e-06, 
        1.8649940680806e-06, 8.7517439682173e-24, 4.3621551072316e-27, 
        2.553168170837e-28, 3.6469582463164e-20, 1.0032983660212e-15, 
        0.00019385229409318, 1.9830820164805e-06, 1.7760568361323e-12, 
        2.919419915209e-05, 1.8741284335866e-06, 2.8285944348148e-25, 
        4.1960751547207e-27, 7.8468215407139e-29, 8.0407329049747e-16, 
        1.9380328071065e-12, 0.00020004849911333, 1.9393279417733e-06, 
        5.9354475879597e-10, 6.4258355913627e-10, 2.6065221215415e-05
        )), class = "data.frame", row.names = c(NA, -100L), .Names = c("run", 
    "repetition", "module", "configname", "packetByteLength", "numVehicles", 
    "dDistance", "time", "distanceToTx", "headerNoError", "receivedPower_dbm", 
    "snr", "frameId", "packetOkSinr", "snir", "ookSnirBer", "ookSnrBer"
    ))
    

    Finding the transformation function

    • y1 - > y2此功能用于根据第一个y轴将辅助y轴的数据转换为"normalized"

    enter image description here

    转换功能: f(y1) = 0.025*x + 2.75


    • y2 - > y1此函数用于将第一个y轴的断点转换为第二个y轴的值 . 请注意,轴现在已交换 .

    enter image description here

    转换功能: f(y1) = 40*x - 110


    Plotting

    注意如何在 ggplot 调用中使用转换函数来转换数据"on-the-fly"

    ggplot(data=combined_80_8192 %>% filter (time > 270, time < 280), aes(x=time) ) +
      stat_summary(aes(y=receivedPower_dbm ), fun.y=mean, geom="line", colour="black") +
      stat_summary(aes(y=packetOkSinr*40 - 110 ), fun.y=mean, geom="line", colour="black", position = position_dodge(width=10)) +
      scale_x_continuous() +
      scale_y_continuous(breaks = seq(-0,-110,-10), "y_first", sec.axis=sec_axis(~.*0.025+2.75, name="y_second") )
    

    第一个 stat_summary 调用是为第一个y轴设置基础的调用 . 调用第二个 stat_summary 调用来转换数据 . 请记住,所有数据都将作为第一个y轴的基础 . 因此,需要针对第一个y轴对数据进行归一化 . 为此,我在数据上使用转换函数: y=packetOkSinr*40 - 110

    现在要转换第二个轴,我在 scale_y_continuous 调用中使用相反的函数: sec.axis=sec_axis(~.*0.025+2.75, name="y_second") .

    enter image description here

  • 8

    我们绝对可以使用基本R函数 plot 构建具有双Y轴的图 .

    # pseudo dataset
    df <- data.frame(x = seq(1, 1000, 1), y1 = sample.int(100, 1000, replace=T), y2 = sample(50, 1000, replace = T))
    
    # plot first plot 
    with(df, plot(y1 ~ x, col = "red"))
    
    # set new plot
    par(new = T) 
    
    # plot second plot, but without axis
    with(df, plot(y2 ~ x, type = "l", xaxt = "n", yaxt = "n", xlab = "", ylab = ""))
    
    # define y-axis and put y-labs
    axis(4)
    with(df, mtext("y2", side = 4))
    
  • 4

    您可以在变量上使用 facet_wrap(~ variable, ncol= ) 来创建新的比较 . 它不在同一轴上,但它是相似的 .

  • 6

    我承认并同意hadley(和其他人),单独的y尺度是"fundamentally flawed" . 话虽如此 - 我经常希望 ggplot2 具有该功能 - 特别是当数据处于wide-format时,我很快想要可视化或检查数据(即仅供个人使用) .

    虽然 tidyverse 库可以很容易地将数据转换为长格式(这样 facet_grid() 可以工作),但这个过程仍然不是很简单,如下所示:

    library(tidyverse)
    df.wide %>%
        # Select only the columns you need for the plot.
        select(date, column1, column2, column3) %>%
        # Create an id column – needed in the `gather()` function.
        mutate(id = n()) %>%
        # The `gather()` function converts to long-format. 
        # In which the `type` column will contain three factors (column1, column2, column3),
        # and the `value` column will contain the respective values.
        # All the while we retain the `id` and `date` columns.
        gather(type, value, -id, -date) %>%
        # Create the plot according to your specifications
        ggplot(aes(x = date, y = value)) +
            geom_line() +
            # Create a panel for each `type` (ie. column1, column2, column3).
            # If the types have different scales, you can use the `scales="free"` option.
            facet_grid(type~., scales = "free")
    
  • 13

    您可以创建应用于第二个geom和右y轴的缩放系数 . 这源于塞巴斯蒂安的解决方案 .

    library(ggplot2)
    
    scaleFactor <- max(mtcars$cyl) / max(mtcars$hp)
    
    ggplot(mtcars, aes(x=disp)) +
      geom_smooth(aes(y=cyl), method="loess", col="blue") +
      geom_smooth(aes(y=hp * scaleFactor), method="loess", col="red") +
      scale_y_continuous(name="cyl", sec.axis=sec_axis(~./scaleFactor, name="hp")) +
      theme(
        axis.title.y.left=element_text(color="blue"),
        axis.text.y.left=element_text(color="blue"),
        axis.title.y.right=element_text(color="red"),
        axis.text.y.right=element_text(color="red")
      )
    

    enter image description here

    注意:使用 ggplot2 v3.0.0

  • 89

    The answer by Hadley对Stephen Few的报告Dual-Scaled Axes in Graphs Are They Ever the Best Solution?给出了一个有趣的参考 .

    我不知道OP对"counts"和_1775939的含义是什么,但快速搜索给了我Counts and Rates,所以我得到一些关于北美登山事故1的数据:

    Years<-c("1998","1999","2000","2001","2002","2003","2004")
    Persons.Involved<-c(281,248,301,276,295,231,311)
    Fatalities<-c(20,17,24,16,34,18,35)
    rate=100*Fatalities/Persons.Involved
    df<-data.frame(Years=Years,Persons.Involved=Persons.Involved,Fatalities=Fatalities,rate=rate)
    print(df,row.names = FALSE)
    
     Years Persons.Involved Fatalities      rate
      1998              281         20  7.117438
      1999              248         17  6.854839
      2000              301         24  7.973422
      2001              276         16  5.797101
      2002              295         34 11.525424
      2003              231         18  7.792208
      2004              311         35 11.254019
    

    然后我尝试在上述报告的第7页中提到的图表(并且按照OP的要求将计数图表绘制成条形图并将费率绘制为折线图):

    另一个不太明显的解决方案,仅适用于时间序列,是通过显示每个值与参考(或索引)值之间的百分比差异,将所有值集转换为通用的定量比例 . 例如,选择特定时间点,例如图表中显示的第一个时间间隔,并将每个后续值表示为它与初始值之间的百分比差异 . 这是通过将每个时间点的值除以初始时间点的值,然后将其乘以100以将速率转换为百分比来完成的,如下所示 .

    df2<-df
    df2$Persons.Involved <- 100*df$Persons.Involved/df$Persons.Involved[1]
    df2$rate <- 100*df$rate/df$rate[1]
    plot(ggplot(df2)+
      geom_bar(aes(x=Years,weight=Persons.Involved))+
      geom_line(aes(x=Years,y=rate,group=1))+
      theme(text = element_text(size=30))
      )
    

    这就是结果:
    enter image description here

    但我不喜欢它而且我无法轻易将传奇放在上面......

    1 WILLIAMSON,Jed,et al . 2005年北美登山事故 . 登山者书籍,2005年 .

  • 79

    有一些常见的使用情况决定y轴,例如climatograph显示月温度和降水量 . 这是一个简单的解决方案,从Megatron的解决方案中推广,允许您将变量的下限设置为零以外的其他值:

    示例数据:

    climate <- tibble(
      Month = 1:12,
      Temp = c(-4,-4,0,5,11,15,16,15,11,6,1,-3),
      Precip = c(49,36,47,41,53,65,81,89,90,84,73,55)
      )
    

    手动设置每个轴的限制:

    ylim.prim <- c(0, 180)   # in this example, precipitation
    ylim.sec <- c(-4, 18)    # in this example, temperature
    

    以下内容根据这些限制进行必要的计算,并使图表本身:

    b <- diff(ylim.prim)/diff(ylim.sec)
    a <- b*(ylim.prim[1] - ylim.sec[1])
    
    ggplot(climate, aes(Month, Precip)) +
      geom_col() +
      geom_line(aes(y = a + Temp*b), color = "red") +
      scale_y_continuous("Precipitation", sec.axis = sec_axis(~ (. - a)/b, name = "Temperature")) +
      scale_x_continuous("Month", breaks = 1:12) +
      ggtitle("Climatogram for Oslo (1961-1990)")
    

    Climatogram showing temperature as line and precipitation as barplot

    如果要确保红线对应于右侧y轴,可以在代码中添加 theme 句子:

    ggplot(climate, aes(Month, Precip)) +
      geom_col() +
      geom_line(aes(y = a + Temp*b), color = "red") +
      scale_y_continuous("Precipitation", sec.axis = sec_axis(~ (. - a)/b, name = "Temperature")) +
      scale_x_continuous("Month", breaks = 1:12) +
      theme(axis.line.y.right = element_line(color = "red"), 
            axis.ticks.y.right = element_line(color = "red"),
            axis.text.y.right = element_text(color = "red"), 
            axis.title.y.right = element_text(color = "red")
            ) +
      ggtitle("Climatogram for Oslo (1961-1990)")
    

    右手轴的颜色:

    Climatogram with red right-hand axis

相关问题