如何使饼图的标记线大于默认值?

时间:2015-01-29 15:08:50

标签: r

我想在打印的切片标记线的角度上使线条更长且不同。

注意:我不是在谈论clockwise = TRUE

代码:

pie.sales <- c(0.12, 0.3, 0.26, 0.16, 0.04, 0.12)
names(pie.sales) <- c("Blueberry", "Cherry","Apple", "Boston Cream", "Other", "Vanilla Cream")
pie(pie.sales)

1 个答案:

答案 0 :(得分:1)

不幸的是,该行的长度在函数中是硬编码的。如果您查看该函数(只需键入pie),请查看底部:

function (x, labels = names(x), edges = 200, radius = 0.8, clockwise = FALSE, 
    init.angle = if (clockwise) 90 else 0, density = NULL, angle = 45, 
    col = NULL, border = NULL, lty = NULL, main = NULL, ...) 
{
    if (!is.numeric(x) || any(is.na(x) | x < 0)) 
        stop("'x' values must be positive.")
## ...snip... ##
        if (!is.na(lab) && nzchar(lab)) {
            lines(c(1, 1.05) * P$x, c(1, 1.05) * P$y)
            text(1.1 * P$x, 1.1 * P$y, labels[i], xpd = TRUE, 
                adj = ifelse(P$x < 0, 1, 0), ...)
        }
    }
    title(main = main, ...)
    invisible(NULL)
}

您可以看到线路长度的硬编码1.05(两次)和文本放置的1.1(两次)。如果您使用此功能,复制它,并将其重新定义为新功能(可能在.R脚本文件中),您可以修复此功能以供自己使用。

两种技巧:

  1. 您可以采用与原作者相同的技巧,并将不同的魔术常量编码到代码中;或

  2. 您可以添加一些选项,以便控制线条的长度和(可选)线条与文本之间的间隙。

  3. 我已经完成了#2,下面。我更改了参数的定义(在function(...)内)以及这两行到底部,仅此而已:

    mypie <- function (x, labels = names(x), edges = 200, radius = 0.8, clockwise = FALSE, 
        init.angle = if (clockwise) 90 else 0, density = NULL, angle = 45, 
        col = NULL, border = NULL, lty = NULL, main = NULL, len = 0.05, lengap = 0.1, ...) 
    {
        if (!is.numeric(x) || any(is.na(x) | x < 0)) 
            stop("'x' values must be positive.")
    ## ...snip... ##
            if (!is.na(lab) && nzchar(lab)) {
                lines(c(1, 1 + len) * P$x, c(1, 1 + len) * P$y)
                text((1 + len + lengap) * P$x, (1 + len + lengap) * P$y, labels[i], xpd = TRUE, 
                    adj = ifelse(P$x < 0, 1, 0), ...)
            }
        }
        title(main = main, ...)
        invisible(NULL)
    }
    

    有了这个,您可以将通话更改为mypie(pie.sales, radius = 0.5, len = 0.6, lengap = 0.3)New pie chart

    现在,接下来的问题是如何让标签在刻度线上更好地对齐,但这是一个不同的问题(并且会花费你为这个答案付出的两倍)。

    修改

    每个标签可以有不同的长度,可能是为了减轻重叠标签。也许有更好的方法可以做到这一点,但是有点蛮力和肘部油脂对程序员的灵魂不时有用......

    在函数末尾的for(i in 1L:nx)行之前,添加:

            list(x = radius * cos(t2p), y = radius * sin(t2p))
        }
        if (length(len) == 1) len <- rep(len, length(x))          # new
        if (length(lengap) == 1) lengap <- rep(lengap, length(x)) # new
        for (i in 1L:nx) { 
            n <- max(2, floor(edges * dx[i]))
    

    (前两行和最后两行仅供上下文使用。)

    现在相应地更改linestext行(添加每个切片的子集):

            if (!is.na(lab) && nzchar(lab)) {
                lines(c(1, 1 + len[i]) * P$x, c(1, 1 + len[i]) * P$y)
                text((1 + len[i] + lengap[i]) * P$x, (1 + len[i] + lengap[i]) * P$y, labels[i], xpd = TRUE, 
                    adj = ifelse(P$x < 0, 1, 0), ...)
            }
    

    现在为饼图的每个切片设置len,顺序相同:

    mypie(pie.sales, len = c(0.05, 0.05, 0.05, 0.25, 0.1, 0.05))
    

    New pie chart, take two