双x轴(模拟到doubleYScale),格子额外或类似

时间:2015-11-07 01:25:10

标签: r graphics lattice plotly

我想在海洋学中提供我们需要的具体数字。不幸的是,在R中实现了双轴,三轴或更多轴不是很好。我不需要双y轴,如格子额外的doubleYScale。我需要双轴或三轴x轴。我无法找到一种方法来使用doubleYScale。也许这是可能的。帮助将非常感激。

这就是我现在所基于的数据:

stackoverflow_fluo.csv:http://pastebin.com/embed_js.php?i=7KNEiytF

animals_stackoverflow.csv:http://pastebin.com/embed_js.php?i=CnEJaq6b

重要更新:我忘了提到两个数据集的y轴上的深度值是不同的间距。

library(latticeExtra)
#dataset 1

    data1011 <- file.path('stackoverflow_fluo.csv')
    jdatax1 = read.csv(data1011)
    jdatax1$stat<-as.factor(jdatax1$Station)

    #dataset2

    data1012 <- file.path('animals_stackoverflow.csv')
    jdatax2 = read.csv(data1012)
    jdatax2$stat<-as.factor(jdatax2$stat)

    #attempt multi axes

    animals<-barchart( depth_good ~Mass | stat, data = jdatax2)
    fluo<-xyplot( depth~chl | stat, data = jdatax1, type = "l")
    doubleYScale(animals, fluo)

    #plot
    jpeg("double_y", width = 11, height = 8.5, units = 'in', res = 300)
    doubleYScale(animals, fluo)
    dev.off()

enter image description here

除了粉红色数据(荧光)需要它自己的轴之外,我需要的是完全相同的。条形图必须是这样的,但实际上我想让y轴反转,使0位于顶部。实际数据也有更多的站点,因此它就像8个数据板。

期待看到这可以做些什么! 非常感谢!

编辑: 添加了示例。见这里:

enter image description here PS。我并不是说我希望看起来像那样的东西或者有太多的轴。但是两个x会很好-.-

1 个答案:

答案 0 :(得分:2)

据我所知,这里没有预先包装的解决方案来解决更普遍的问题。

下面的示例介绍了添加其他轴的几种方法。第二种更通用的方法(即使在沿着绘图的边界添加轴时,我倾向于使用它)的工作原理是首先推动视口,然后沿其边缘添加轴。通过将视口推到一英寸高(例如),它允许您生成一个在图上方浮动一英寸的轴。使用提供的xlim=参数推送视口还允许您设置其原始坐标系,这允许您回避一些其他需要的坐标系转换。

以下中等评论的代码中还有更多内容,我将让您自己探索!

library(lattice)
library(grid)

## Functions for converting units between axes
year2salinity <- function(year) {33 + (1/30)*(year-1900)}
salinity2year <- function(salinity) 1900 + 30*(salinity-33)
year2copepod <- function(year) {1000 + 100*(year-1900)}

## A better pretty(). (base::pretty() will often return limits that
## run beyond plot's ends.)
prettyBetween <- function(x,...) {
    xx <- pretty(x,...)
    xx[xx >= min(x) & xx <= max(x)]
}

## Custom axis-drawing function to be invoked via xyplot(..., axis=customAxis)
customAxis <- function(side, ...) {
    if (side == "top") {
        xlim <- current.panel.limits()$xlim
        ## Method #1 (Only works for axis along side of plot)
        atSalinity <- prettyBetween(year2salinity(xlim))
        panel.axis(side = side, outside = TRUE, at=salinity2year(atSalinity),
                   labels = as.character(atSalinity),
                   rot=0)
        grid.text("Salinity", gp=gpar(cex=0.9),
                  y=unit(1, "npc") + unit(2.5, "lines"))
        ## Method #2 (Works for "floating" axis or -- with viewport height=0 --
        ##            for axis along side of plot.)
        atCopepod <- prettyBetween(year2copepod(xlim))
        pushViewport(viewport(height = unit(4, "lines"),
                              y = 1, just = "bottom",
                              xscale = year2copepod(xlim)))
        panel.axis(side = side, outside = TRUE, at=atCopepod,
                   labels = as.character(atCopepod),
                   line.col = "grey65", text.col = "grey35", rot=0)
        ## panel.axis doesn't draw the axis' "baseline", so we do it using grid.axis  
        grid.xaxis(at = atCopepod, label = FALSE,
                   main = FALSE, gp = gpar(col="grey65"))
        grid.text(expression("Copepods m"^{-3}), gp=gpar(cex=0.9, col="grey35"),
                  y=unit(1, "npc") + unit(2.5, "lines"))
        popViewport()
    }
    else {
        axis.default(side = side, ...)
    }
}

xyplot(nhtemp ~ time(nhtemp), aspect = "xy", type = "o",
       xlab = "Year", ylab = "Temperature",
       axis = customAxis,
       main = "Yearly temperature, salinity, and copepod abundance",
       scales = list(x=list(alternating=3)),
       ## Set up key.axis.padding (an element of each lattice plot's layout) to
       ## understand values in terms of lines...
       lattice.options=list(layout.heights=list(key.axis.padding=list(x=1,units="lines"))),
       ## ... so that you can tell it you need 6 "lines" of space for axes
       par.settings = list(layout.heights=list(key.axis.padding=6)))

enter image description here

补充说明,主要是为了我自己:

上述代码需要调用panel.axis()grid.xaxis(),这不是很理想。我们需要调用grid.xaxis()(并且,就此而言,定义函数prettyBetween())的唯一原因是panel.axis()绘制刻度和标签,但不绘制轴基线。如果panel.axis()可以选择这样做,那么这里的事情就会简单得多。要查看它会是什么样的,请运行trace()为每个panel.axis()调用添加一些额外的基线绘图代码......

trace(panel.axis,
      exit=expression(
      grid.lines(x = unit(at[c(1,length(at))], "native"),
                    y = unit(c(1,1), "npc"),
                    gp = gp.line)))

....之后调用面板轴(带side=="top")将绘制我们想要的基线。