How to draw a circle in a log-log plot in R?

本秂侑毒 提交于 2019-12-06 04:48:37

问题


I have a plot with two logarithmic axes. I'd like to add a circle to a certain position of the plot. I tried to use plotrix, but this does not give options for "log-radius".

# data to plot
x = 10^(-1 * c(5:0))
y = x ^-1.5

#install.packages("plotrix", dependencies=T)
# use require() within functions
library("plotrix")

plot (x, y, log="xy", type="o")
draw.circle(x=1e-2, y=1e2, radius=1e1, col=2)

How can I add a circle to my log-log plot?


回答1:


As krlmlr suggests, the easiest solution is to slightly modify plotrix::draw.circle(). The log-log coordinate system distorts coordinates of a circle given in the linear scale; to counteract that, you just need to exponentiate the calculated coordinates, as I've done in the lines marked with ## <- in the code below:

library("plotrix")

draw.circle.loglog <- 
function (x, y, radius, nv = 100, border = NULL, col = NA, lty = 1,
    lwd = 1)
{
    xylim <- par("usr")
    plotdim <- par("pin")
    ymult <- (xylim[4] - xylim[3])/(xylim[2] - xylim[1]) * plotdim[1]/plotdim[2]
    angle.inc <- 2 * pi/nv
    angles <- seq(0, 2 * pi - angle.inc, by = angle.inc)
    if (length(col) < length(radius))
        col <- rep(col, length.out = length(radius))
    for (circle in 1:length(radius)) {
        xv <- exp(cos(angles) * log(radius[circle])) * x[circle]         ## <-
        yv <- exp(sin(angles) * ymult * log(radius[circle])) * y[circle] ## <-
        polygon(xv, yv, border = border, col = col[circle], lty = lty,
            lwd = lwd)
    }
    invisible(list(x = xv, y = yv))
}

# Try it out 
x = 10^(-1 * c(5:0))
y = x ^-1.5

plot (x, y, log="xy", type="o")
draw.circle.loglog(x = c(1e-2, 1e-3, 1e-4), y = c(1e2, 1e6, 1e2),
                   radius = c(2,4,8), col = 1:3)




回答2:


A work around would be to apply log10 explicitly.

plot (log10(x), log10(y), type="o")
draw.circle(x=log10(1e-2), y=log10(1e2), radius=log10(1e1), col=2)

Edit (using symbols):

plot (x, y, log="xy", type="o",xlim=c(1e-5,1), ylim=c(1,1e8))
par(new=T)
symbols(x=1e-2, y=1e2, circles=1e1, xlim=c(1e-5,1), ylim=c(1,1e8), 
        xaxt='n', yaxt='n', ann=F, log="xy")



回答3:


The function draw.circle from the plotrix package looks like that on my system:

> draw.circle
function (x, y, radius, nv = 100, border = NULL, col = NA, lty = 1, 
    lwd = 1) 
{
    xylim <- par("usr")
    plotdim <- par("pin")
    ymult <- (xylim[4] - xylim[3])/(xylim[2] - xylim[1]) * plotdim[1]/plotdim[2]
    angle.inc <- 2 * pi/nv
    angles <- seq(0, 2 * pi - angle.inc, by = angle.inc)
    if (length(col) < length(radius)) 
        col <- rep(col, length.out = length(radius))
    for (circle in 1:length(radius)) {
        xv <- cos(angles) * radius[circle] + x
        yv <- sin(angles) * radius[circle] * ymult + y
        polygon(xv, yv, border = border, col = col[circle], lty = lty, 
            lwd = lwd)
    }
    invisible(list(x = xv, y = yv))
}
<environment: namespace:plotrix>

What happens here is essentially that the circle is approximated by a polygon of 100 vertices (parameter nv). You can do either of the following:

  • Create your own version of draw.circle that does the necessary coordinate transformation to "undo" the log transform of the axes.

  • The function invisibly returns the list of coordinates that are used for plotting. (If you pass a vector as radius, then only the coordinates of the last circle are returned.) You might be able to apply a transform to those coordinates and call polygon on the result. Pass appropriate values for border, col, lty and/or lwd to hide the polygon drawn by the functions itself.

The first version sounds easier to me. Simply replace the + x by a * x, same for y, inside the for loop, and you're done. Equivalently, for the second version, you subtract x and then multiply by x each coordinate, same for y. EDIT: These transformations are slightly wrong, see Josh's answer for the correct ones.



来源:https://stackoverflow.com/questions/15921359/how-to-draw-a-circle-in-a-log-log-plot-in-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!