[R] plot level, velocity, acceleration with one x axis

Spencer Graves @pencer@gr@ve@ @end|ng |rom e||ect|vede|en@e@org
Wed May 31 17:45:17 CEST 2023



On 5/31/23 9:20 AM, Eric Berger wrote:
> I sent you an updated response to deal with the redundant copies of the x-axis.
> Re-sending.
> 
par(mfrow=c(3,1))
plot(DAX.[, 1], log='y', ylab='DAX', xaxt="n")
plot(DAX.[, 2], ylab='vel (%)', xaxt="n")
plot(DAX.[, 3], ylab='accel (%)')


	  I got that.  The primary problem with that is that most of the 
vertical space is reserved for axis labels, whether they are printed or 
not.  If I squeeze the vertical dimension of the plot, I get, "figure 
margins too large".  To control that, I need to set "mar" separately for 
each panel, and then the plot regions for each are not the same size. 
Using the "layout" function instead of "mfrow" is better, but I don't 
see now to make that work consistently without fixing the aspect ratio. 
There may be a way in the tidyverse, but I haven't found it yet.  The 
only solution I've found so far that makes sense to me is to modify the 
code for plot.ts to accept a vector for the log argument, with the 
constraint that length(lot) = either 1 or ncol(x) and returning 
invisibly an object that would make it feasible for a user to call 
axis(2, ...) once for each vertical axis to handle cases where someone 
wanted to a vertical scale different from linear and log.  I'd want to 
make sure that lines.ts also works with this, because I want to add fits 
and predictions.


	  Comments?
	  Thanks,
	  Spencer Graves


** With either of the following plots, if I adjust the aspect ratio by 
enlarging or reducing the vertical dimension of the plot, the relative 
sizes of the plot regions change.


DAX <- EuStockMarkets[, 'DAX']
DAX. <- cbind(DAX, diff(log(DAX)), diff(diff(log(DAX))))
colnames(DAX.) <- c("DAX", 'vel (%)', 'accel (%)')
head(DAX.)

plot(DAX., log='xy')

op <- par(mfrow=c(3,1), mar=c(0, 4.1, 4.1, 2.1))
plot(DAX.[, 1], log='y', ylab='DAX', axes=FALSE)
axis(2)
box(col='grey')
par(mar=c(0, 4.1, 0, 2.1))
plot(DAX.[, 2], ylab='vel (%)', axes=FALSE)
axis(2)
box(col='grey')
par(mar=c(5.1, 4.1, 0, 2.1))
plot(DAX.[, 3], ylab='accel (%)', axes=FALSE)
axis(2)
box(col='grey')
axis(1)
par(op)


 > sessionInfo()
R version 4.3.0 (2023-04-21)
Platform: x86_64-apple-darwin20 (64-bit)
Running under: macOS Big Sur 11.7.7

Matrix products: default
BLAS: 
/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 

LAPACK: 
/Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/lib/libRlapack.dylib; 
  LAPACK version 3.11.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/Chicago
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

loaded via a namespace (and not attached):
[1] compiler_4.3.0  tools_4.3.0     rstudioapi_0.14
> 
> 
> On Wed, May 31, 2023 at 4:27 PM Spencer Graves
> <spencer.graves using effectivedefense.org> wrote:
>>
>>
>>
>> On 5/30/23 10:23 AM, Eric Berger wrote:
>>> What if you just precede these commands as follows:
>>>
>>> par(mfrow=c(3,1))
>>> plot(DAX.[, 1], log='y', ylab='DAX')
>>> plot(DAX.[, 2], ylab='vel (%)')
>>> plot(DAX.[, 3], ylab='accel (%)')
>>
>>            Most of the space is consumed with two extraneous copies of the axis.
>>    We can get around that with three calls to par:
>>
>>
>> op <- par(mfrow=c(3,1), mar=c(0, 4.1, 4.1, 2.1))
>> plot(DAX.[, 1], log='y', ylab='DAX')
>> par(mar=c(0, 4.1, 0, 2.1))
>> plot(DAX.[, 2], ylab='vel (%)')
>> par(mar=c(5.1, 4.1, 0, 2.1))
>> plot(DAX.[, 3], ylab='accel (%)')
>> par(op)
>>
>>
>>            However, the three panels are NOT equal in size:  roughly 30% vs. 44%
>> vs. 26%.  I can get closer using layout, but if I change the aspect
>> ratio, it changes the relationship between the heights of the three
>> panels.
>>
>>
>>            That's the problem I'm trying to solve.  It's also why it makes sense
>> to me to modify plot.ts to accept a vector for the log argument, with
>> the constraint that length(lot) = either 1 or ncol(x).
>>
>>
>>            There may be a way to do it using gglot2 / the tidyverse, but I'm not
>> facile with that, and my web searches have so far failed to produce
>> anything better than modifying plot.ts.R (and then submitting such with
>> compatible changes to plot.ts.Rd), as I suggested earlier.
>>
>>
>>            ???
>>            Thanks,
>>            Spencer
>>
>>>
>>> On Tue, May 30, 2023 at 5:45 PM Spencer Graves
>>> <spencer.graves using effectivedefense.org> wrote:
>>>>
>>>>
>>>>
>>>> On 5/30/23 8:48 AM, Eric Berger wrote:
>>>>> I am a bit confused as to what you are trying to achieve - and  even
>>>>> if I could guess it is not clear what the interpretation would be.
>>>>>> head(DAX)
>>>>> 1628.75 1613.63 1606.51 1621.04 1618.16 1610.61
>>>>>
>>>>> Including the leading NA's, what would be the 6 leading terms of the 3
>>>>> series that you want to plot,
>>>>> and what would be the Y labels that you want to appear at those levels
>>>>> (assuming that there was a
>>>>> Y label for each of them - just to understand the units you are talking about)
>>>>
>>>>
>>>> DAX <- EuStockMarkets[, 'DAX']
>>>> DAX. <- cbind(DAX, diff(log(DAX)), diff(diff(log(DAX))))
>>>> colnames(DAX.) <- c("DAX", 'vel (%)', 'accel (%)')
>>>> head(DAX.)
>>>>
>>>>
>>>>             DAX exhibits growth that is roughly exponential, so I want to plot it
>>>> on a log scale:
>>>>
>>>>
>>>> plot(DAX.[, 1], log='y', ylab='DAX')
>>>> plot(DAX.[, 2], ylab='vel (%)')
>>>> plot(DAX.[, 3], ylab='accel (%)')
>>>>
>>>>
>>>>             This is what I want as three panels of a single plot.
>>>>
>>>>
>>>>             I think I could get it by modifying the code for plot.ts so it
>>>> accepted ylab as a vector, etc., as I previously mentioned.
>>>>
>>>>
>>>>             What do you think?
>>>>             Thanks,
>>>>             Spencer Graves
>>>>>
>>>>>
>>>>> On Tue, May 30, 2023 at 4:06 PM Spencer Graves
>>>>> <spencer.graves using effectivedefense.org> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 5/30/23 6:16 AM, Eric Berger wrote:
>>>>>>> My code assumes that DAX is a ts object, as in your original post.
>>>>>>>
>>>>>>> On Tue, May 30, 2023 at 2:06 PM Eric Berger <ericjberger using gmail.com> wrote:
>>>>>>>>
>>>>>>>> Untested but why not
>>>>>>>>
>>>>>>>> a <- cbind(log(DAX), exp(diff(log(DAX))), exp(diff(diff(log(DAX)))))
>>>>>>>> colnames(a) <- c("logDAX", "vel", "accel")
>>>>>>>> plot(a)
>>>>>>
>>>>>>
>>>>>>              Progress, but we're not there yet.
>>>>>>
>>>>>>
>>>>>> a <- cbind(DAX, exp(diff(log(DAX))), exp(diff(diff(log(DAX)))))
>>>>>> colnames(a) <- c("logDAX", "vel", "accel")
>>>>>> plot(a)
>>>>>> plot(a, axes=FALSE, log='y')
>>>>>> axis(1)
>>>>>> axis(2)
>>>>>>
>>>>>>
>>>>>>              How do I get each y axis labeled in its original units?  I can use
>>>>>> pretty to get where I want tick marks, but I don't know where to place
>>>>>> them "at" in calling axis(2, at= ___)?
>>>>>>
>>>>>>
>>>>>> (axlb1 <- pretty(range(a[, 1])))
>>>>>> (axlb2 <- pretty(range(log(a[, 2]), na.rm=TRUE)))
>>>>>> (axlb3 <- pretty(range(log(a[, 3]), na.rm=TRUE)))
>>>>>>
>>>>>>
>>>>>>              This suggests I write my own modification of plot.ts that accepts log
>>>>>> as a character vector of length = ncol of the ts being plotted and
>>>>>> returns invisibly a list with the default "at" and "label" arguments
>>>>>> required to produce the default labeling.  Then a user who wants a log
>>>>>> scale for some but not all variables can get that easily and can further
>>>>>> modify any of those scales further if they don't like the default.
>>>>>>
>>>>>>
>>>>>>              ???
>>>>>>              Thanks very much.
>>>>>>              Spencer Graves
>>>>>>>>
>>>>>>>>
>>>>>>>> On Tue, May 30, 2023 at 1:46 PM Spencer Graves
>>>>>>>> <spencer.graves using effectivedefense.org> wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 5/29/23 2:37 AM, Eric Berger wrote:
>>>>>>>>>> How about this:
>>>>>>>>>>
>>>>>>>>>> a <- cbind(AirPassengers, diff(log(AirPassengers)),
>>>>>>>>>> diff(diff(log(AirPassengers))))
>>>>>>>>>> colnames(a)[2:3] <- c("percent increase", "acceleration")
>>>>>>>>>> plot(a, xlab="year", main="AirPassengers")
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>               My real problem is more difficult:  I'm analyzing CO2 data from Our
>>>>>>>>> World in Data (https://ourworldindata.org/co2-emissions), and I need to
>>>>>>>>> plot the CO2 data on a log scale but velocity and acceleration on linear
>>>>>>>>> scales.  The following is comparable:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> str(DAX <- EuStockMarkets[, 'DAX'])
>>>>>>>>> str(DAX. <- cbind(DAX, diff(log(DAX)),
>>>>>>>>>                        diff(diff(log(DAX)))))
>>>>>>>>> colnames(DAX.)[2:3] <- c('vel', 'accel')
>>>>>>>>> plot(DAX.)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>               I want the first of the three panels to plot on the log scale, but
>>>>>>>>> the other two on linear scales.  The obvious attempt does not work:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> plot(DAX., log=c('y', '', ''))
>>>>>>>>> #Error in length(log) && log != "" :
>>>>>>>>> #  'length = 3' in coercion to 'logical(1)'
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>               Trying to construct my own axes isn't easy, either:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> str(logDAX <- cbind(log(DAX), diff(log(DAX)),
>>>>>>>>>                        diff(diff(log(DAX)))))
>>>>>>>>> colnames(logDAX) <- c('logDAX', 'vel', 'accel')
>>>>>>>>> plot(logDAX, axes=FALSE)
>>>>>>>>> axis(1)
>>>>>>>>> axis(2)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>               I'm thinking of creating my own copy of "plot.ts", and changing it so
>>>>>>>>> it accepts the "log" argument as a vector of length equal to ncol of the
>>>>>>>>> ts object to be plotted AND returning an object that would allow a user
>>>>>>>>> to call "axis" ncol times.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>               Suggestions?
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>               Thanks,
>>>>>>>>>               Spencer Graves
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> HTH,
>>>>>>>>>> Eric
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Mon, May 29, 2023 at 7:57 AM Spencer Graves
>>>>>>>>>> <spencer.graves using effectivedefense.org> wrote:
>>>>>>>>>>>
>>>>>>>>>>> Hello, All:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>                I want to plot level, velocity, and acceleration in three panels with
>>>>>>>>>>> only one x axis.  The code below does this using "layout".  However, I
>>>>>>>>>>> want the three plot areas to be of equal size, and this won't do that:
>>>>>>>>>>> If I stretch the plot vertically, the relative sizes of the three panels
>>>>>>>>>>> changes.  There's probably a way to do this with ggplot2, but I have yet
>>>>>>>>>>> to find it.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>                Suggestions?
>>>>>>>>>>>                Thanks,
>>>>>>>>>>>                Spencer Graves
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> str(AirTime <- as.numeric(time(AirPassengers)))
>>>>>>>>>>> str(AP <- as.numeric(AirPassengers))
>>>>>>>>>>>
>>>>>>>>>>> def.par <- par(no.readonly = TRUE) # save default, for resetting...
>>>>>>>>>>> (mat3x1 <- matrix(1:3, 3))
>>>>>>>>>>> plot3x1 <- layout(mat3x1, heights=c(1.4, 1, 1.5))
>>>>>>>>>>> layout.show(plot3x1)
>>>>>>>>>>>
>>>>>>>>>>> par(mar=c(0, 4.1, 4.1, 2.1))
>>>>>>>>>>> plot(AirTime, AP, log='y', type='l', axes=FALSE,
>>>>>>>>>>>            main='AirPassengers', ylab='AirPassengers')
>>>>>>>>>>> box(col='grey')
>>>>>>>>>>> axis(2, las=1)
>>>>>>>>>>>
>>>>>>>>>>> par(mar=c(0, 4.1, 0, 2.1))
>>>>>>>>>>> vAP <- diff(log(AP))
>>>>>>>>>>> plot(tail(AirTime, -1), vAP, type='l',
>>>>>>>>>>>            ylab='percent increase', axes=FALSE)
>>>>>>>>>>> box(col='grey')
>>>>>>>>>>> axis(2, las=1)
>>>>>>>>>>>
>>>>>>>>>>> par(mar=c(5.1, 4.1, 0, 2.1))
>>>>>>>>>>> plot(tail(AirTime, -2), diff(vAP), type='l',
>>>>>>>>>>>            ylab='acceleration', xlab='year',
>>>>>>>>>>>            las=1)
>>>>>>>>>>> box(col='grey')
>>>>>>>>>>>
>>>>>>>>>>> par(def.par)
>>>>>>>>>>>
>>>>>>>>>>> ______________________________________________
>>>>>>>>>>> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
>>>>>>>>>>> https://stat.ethz.ch/mailman/listinfo/r-help
>>>>>>>>>>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>>>>>>>>>>> and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list