beginner_
beginner_

Reputation: 7632

R: plot() is ignoring xlim

I'm not a heavy r user and if I usually use ggplot2 which is not easily possible in this case.

When I create a plot from a model generated by a 3rd party library, the resulting plots have different x-axis limits even if I explicitly set x-axis limit

plot(model, 
    col = TRUE, 
    pch = 20:25, 
    xlab = "x", 
    ylab = "y", 
    xlim = c(0.0001, 100), 
    ylim = c(0, 200), 
    broken = FALSE,
    main = "My Plot,
    axes = FALSE    
)

axis(side = 1, at = c(1, 10, 100))
axis(1, at=0.1, labels="0.1", tck= -0.04)
axis(1, at=0.01, labels="0.01", tck= -0.04)
axis(1, at=0.001, labels=parse(text="10^-3"), tck= -0.04)
axis(1, at=0.0001, labels=parse(text="10^-4"), tck= -0.04)

axis(2, at=0, labels="0", tck= -0.04, las=1)
axis(2, at=50, labels="50", tck= -0.04, las=1)
axis(2, at=100, labels="100", tck= -0.04, las=1)

Depending on the model the plot doesn't always start at 0.0001 but at 0.001 or 0.1

How can I force the xlim to be respected regardless of the input?

Upvotes: 1

Views: 2375

Answers (1)

Allan Cameron
Allan Cameron

Reputation: 174348

When you run plot(model), you are calling the generic function plot. A generic function examines the "class" attribute of its first argument, then dispatches a specific method for that class. In your example, model is of class "drc", so the function used for plotting is drc:::plot.drc.

If we examine the source code, we see that it includes an add parameter. This gives us a solution - namely, we create a standard empty plot with the correct axis limits, then plot our model with add = TRUE

Here is a worked example using the ryegrass data set, included in the package:

library(drc)

data(ryegrass)

model <- drm(rootl ~ conc, data = ryegrass, fct = W2.4())

Now draw an empty plot with whichever x and y limits we want, but leave the x axis blank:

plot(1, xlim = c(0.0001, 100), ylim = c(0, 10), log = "x", type = "n",
     xaxt = "none")

enter image description here

Now we can add our plot and axis:

plot(model, add = TRUE,
    col = TRUE, 
    pch = 20:25, 
    broken = FALSE,
)

axis(side = 1, at = c(1, 10, 100))
axis(1, at=0.1, labels="0.1", tck= -0.04)
axis(1, at=0.01, labels="0.01", tck= -0.04)
axis(1, at=0.001, labels=parse(text="10^-3"), tck= -0.04)
axis(1, at=0.0001, labels=parse(text="10^-4"), tck= -0.04)

enter image description here

Incidentally, if you prefer ggplot, this remains an option, since you can get the predicted dose-response line using predict

library(ggplot)

df <- data.frame(conc = 10^seq(log10(min(ryegrass$conc[ryegrass$conc > 0])), 
                               log10(max(ryegrass$conc)), 0.01))
df$response <- predict(model, newdata = df)

ggplot(df, aes(conc, response)) +
  stat_summary(fun = mean, geom = "point", 
               data = ryegrass[ryegrass$conc != 0, ], aes(y = rootl)) +
  geom_line() +
  scale_x_log10(
    breaks = 10^seq(-4, 2),
    limits = c(0.0001, 100),
    labels = parse(text = c("10^-4", "10^-3", 0.01, 0.1, 1, 10, 100))) +
  theme_light(base_size = 16) +
  ylim(c(0, 10))

enter image description here

Created on 2022-06-10 by the reprex package (v2.0.1)

Upvotes: 2

Related Questions