khajlk
khajlk

Reputation: 861

How do I change x-axis values in a grouped lattice xyplot

I have following sample data in R.

d <- read.table(text = 
"Grp     Var    Col1  Col2    Col3
grp_1   8      46.8  50.0   50.6
grp_1   16     95.6  47.4   48.0
grp_1   24     45.1  45.6   46.4
grp_1   32     68.8  44.3   58.2
grp_1   40     44.6  52.2   44.3
grp_1   48     86.5  42.2   68.6
grp_2   40     63.2  95.6   63.0
grp_2   60     66.7  67.5   65.6
grp_2   80     69.6  70.7   67.9
grp_2   100    71.9  73.4   69.3
grp_2   120    73.8  75.7   48.0
grp_3   500    51.9  50.0   50.5
grp_3   1000   65.5  53.0   53.4
grp_3   5000   61.2  99.0   59.9
grp_3   10000  80.1  63.0   62.8
grp_3   30000  25.9  33.8   14.2
  ", header=T
)

The columns Col1, Col2, and Col3, for each group, need to be plotted against Var. Group 1 has 6 values each for Var, Col1 - Col3, While groups 2 and 3 have 5 values. I am using Lattice's xyplot() function to plot them in a grid. The code is below:

#Groups as factors
d$Grp <- factor(d$Grp, levels=c("grp_1","grp_2","grp_3"), order=TRUE)
#Plot the data
xyplot(
  Col1 + Col2 + Col3 ~ Var | Grp,
  data=d,
  superpose=T,
  as.table=TRUE,
  col=c("#cc0000","#008000", "#0073e6"),
  lwd=1.5, ylim = c(0,120),
  ylab = list(label=expression("My Values"), fontsize=15),
  xlab = list(label="Var",fontsize=15),
  key=list(
    text  = list(c("Col1", "Col2", "Col3")),
    lines = list( lwd=1.5, col=c("#cc0000","#008000", "#0073e6")),
    corner = c(1, 0),
    x = 0.90, 
    y = 0.17),
  par.settings = list(strip.background=list(col="white")),
  scales=list(cex=1.2),
  type=c("l","g")
)

The plot looks like this:

Code output

Clearly, the group 1 and 2 plotted values look messy because x-axis values are 500,1000,5000,10000,30000 instead of 8,16,24,32,40,48 and 40,60,80,100,120. Is there any way to fix x-axis values for group 1 and 2 using xyplot() (preferably)? I am also open for other cool suggestions. The expected output could for example be like this:

Desired output

Upvotes: 1

Views: 2031

Answers (3)

David O
David O

Reputation: 813

The plot.trellis method allows one to plot lattice objects on a grid. By combining that with update.trellis method, one can create a layout of arbitrary spacings.

I post this answer (a bit late) to highlight these options in lattice. My answer also starts in the spirit of the "tidyverse" by creating a long format for the data.

# first update the lattice parameters in 'tp'
    library(lattice)
    tp <- trellis.par.get() # retrieve all parameters
    tp$strip.background$col <- "white"
    tp$superpose.line$col <- c("#CC0000","#008000", "#0073E6")
    tp$superpose.line$lwd <- 1.5

# data from example already 'd' then convert with simple base functions
    myDat <- cbind(d[1:2], stack(d[3:5])) # new variables: "values" & "ind"

# create single plot object
    obj <- xyplot(values ~ Var | Grp, df, groups = ind, type = c("g", "l"),
        par.settings = tp, scales = list(x = list(relation = "free")),
        ylab = "My Values", xlab = "Place holder", as.table = TRUE)

The lattice object (obj) has the desired format but with only one x-axis label. It can simply be plotted by obj or plot(obj) in almost the desired form. However, since it actually is three lattice plots, they can extracted, updated, and plotted in a grid with the update.trellis and plot.trellis methods as shown here.

# axis labels and key 
    xlabs <- paste("My x-axis title", 1:3)
    myKey = list(corner = c(5, 0.5), points = FALSE, lines = TRUE)

# assemble final plot
    plot(update(o[1], xlab = xlabs[1]), split = c(1,1,2,2), more = TRUE)
    plot(update(o[2], xlab = xlabs[2]), split = c(2,1,2,2), more = TRUE)
    plot(update(o[3], xlab = xlabs[1], auto.key = myKey),
        split = c(1,2,2,2), more = FALSE)

plot produced by update.trellis and plot.trellis By using position option instead of the split option, one can take finer control over the position of each plot.

Upvotes: 0

StupidWolf
StupidWolf

Reputation: 46908

You use the scales option with relation="free", I get a plot similar to @Tjebo's above.. not 3 identical plots:

xyplot(
  Col1 + Col2 + Col3 ~ Var | Grp,
  data=d,
  superpose=T,
  as.table=TRUE,
  col=c("#cc0000","#008000", "#0073e6"),
  lwd=1.5, ylim = c(0,120),
  ylab = list(label=expression("My Values"), fontsize=15),
  xlab = list(label="Var",fontsize=15),
  key=list(
    text  = list(c("Col1", "Col2", "Col3")),
    lines = list( lwd=1.5, col=c("#cc0000","#008000", "#0073e6")),
    corner = c(1, 0),
    x = 0.90, 
    y = 0.17),
  par.settings = list(strip.background=list(col="white")),
  scales=list(cex=1.2,x=list(relation="free")),
  type=c("l","g")
)

enter image description here

Upvotes: 2

tjebo
tjebo

Reputation: 23757

Because you have tagged it ggplot2 as well, here a ggplot2 solution.

I personally think that this is much easier than base plot, but I am incredibly biased.

library(tidyverse)

d_long <- 
  d %>%
    pivot_longer(names_to = "key", values_to = 'value', contains("Col"))

ggplot(d_long, aes(Var, value, color = key)) +
  geom_line() +
  facet_grid(~Grp, scales = "free_x") +
  scale_color_manual(values =c("#cc0000","#008000", "#0073e6"))

Created on 2020-04-28 by the reprex package (v0.3.0)

Upvotes: 1

Related Questions