ggplot,小,饼图:以饼图切片的中间放置文本(ggplot, facet, piechart:

2019-09-01 00:31发布

我想产生一个刻面饼图与ggplot并面临将文本中的每个切片的中部问题:

dat = read.table(text = "Channel Volume Cnt
                         AGENT   high   8344
                         AGENT medium   5448
                         AGENT    low  23823
                         KIOSK   high  19275
                         KIOSK medium  13554
                         KIOSK    low  38293", header=TRUE)

vis = ggplot(data=dat, aes(x=factor(1), y=Cnt, fill=Volume)) +
  geom_bar(stat="identity", position="fill") +
  coord_polar(theta="y") +
  facet_grid(Channel~.) +
  geom_text(aes(x=factor(1), y=Cnt, label=Cnt, ymax=Cnt), 
            position=position_fill(width=1))

输出:

什么参数的geom_text应,以便将数值标签在饼图切片的中间调整?

相关的问题是派阴谋获取其文本在彼此的顶部 ,但它不处理的情况下有小。

更新:继保Hiemstra意见和办法,上面我改变的代码如下问题:

---> pie_text = dat$Cnt/2 + c(0,cumsum(dat$Cnt)[-length(dat$Cnt)])

     vis = ggplot(data=dat, aes(x=factor(1), y=Cnt, fill=Volume)) +
     geom_bar(stat="identity", position="fill") +
     coord_polar(theta="y") +
     facet_grid(Channel~.) +
     geom_text(aes(x=factor(1), 
--->               y=pie_text, 
                   label=Cnt, ymax=Cnt), position=position_fill(width=1))

如我所料的调整文本coordiantes是绝对的,但它需要是小数据中:

Answer 1:

新的应答:通过引入GGPLOT2 V2.2.0的, position_stack()可用于,而不需要先计算的位置可变的标签进行定位。 下面的代码会给你同样的结果旧的答案:

ggplot(data = dat, aes(x = "", y = Cnt, fill = Volume)) + 
  geom_bar(stat = "identity") +
  geom_text(aes(label = Cnt), position = position_stack(vjust = 0.5)) +
  coord_polar(theta = "y") +
  facet_grid(Channel ~ ., scales = "free")

要删除“空心化”的中心,适应的代码:

ggplot(data = dat, aes(x = 0, y = Cnt, fill = Volume)) + 
  geom_bar(stat = "identity") +
  geom_text(aes(label = Cnt), position = position_stack(vjust = 0.5)) +
  scale_x_continuous(expand = c(0,0)) +
  coord_polar(theta = "y") +
  facet_grid(Channel ~ ., scales = "free")

OLD解答:解决这个问题是创建一个位置变量,其可与碱R或与相当容易地进行data.table , plyr或dplyr包:

步骤1:创建位置变量对于每个信道

# with base R
dat$pos <- with(dat, ave(Cnt, Channel, FUN = function(x) cumsum(x) - 0.5*x))

# with the data.table package
library(data.table)
setDT(dat)
dat <- dat[, pos:=cumsum(Cnt)-0.5*Cnt, by="Channel"]

# with the plyr package
library(plyr)
dat <- ddply(dat, .(Channel), transform, pos=cumsum(Cnt)-0.5*Cnt)

# with the dplyr package
library(dplyr)
dat <- dat %>% group_by(Channel) %>% mutate(pos=cumsum(Cnt)-0.5*Cnt)

第2步:创建多面积

library(ggplot2)
ggplot(data = dat) + 
  geom_bar(aes(x = "", y = Cnt, fill = Volume), stat = "identity") +
  geom_text(aes(x = "", y = pos, label = Cnt)) +
  coord_polar(theta = "y") +
  facet_grid(Channel ~ ., scales = "free") 

结果:



Answer 2:

我想站出来反对让在GGPLOT2,这是在极坐标绘制的层叠barplot馅饼的传统方式。 虽然我很欣赏这种方法的数学优雅,但它引起各种头痛时的情节看起来不它应该的方式。 特别是,正是调整蛋糕的大小是很困难的。 (如果你不明白我的意思,尽量使扩展一路情节面板的边缘的饼图。)

我更喜欢在正常笛卡尔绘图馅饼坐标系统,采用geom_arc_bar()从ggforce。 它需要额外的工作,对前端一点点,因为我们要计算自己的角度,但是这很容易控制的,我们得到的结果水平比值得更多。 我已经使用在以前的答案这种方法在这里和这里。

(从问题)中的数据:

dat = read.table(text = "Channel Volume Cnt
AGENT   high   8344
AGENT medium   5448
AGENT    low  23823
KIOSK   high  19275
KIOSK medium  13554
KIOSK    low  38293", header=TRUE)

馅饼拉代码:

library(ggplot2)
library(ggforce)
library(dplyr)

# calculate the start and end angles for each pie
dat_pies <- left_join(dat,
                      dat %>% 
                        group_by(Channel) %>%
                        summarize(Cnt_total = sum(Cnt))) %>%
  group_by(Channel) %>%
  mutate(end_angle = 2*pi*cumsum(Cnt)/Cnt_total,      # ending angle for each pie slice
         start_angle = lag(end_angle, default = 0),   # starting angle for each pie slice
         mid_angle = 0.5*(start_angle + end_angle))   # middle of each pie slice, for the text label

rpie = 1 # pie radius
rlabel = 0.6 * rpie # radius of the labels; a number slightly larger than 0.5 seems to work better,
                    # but 0.5 would place it exactly in the middle as the question asks for.

# draw the pies
ggplot(dat_pies) + 
  geom_arc_bar(aes(x0 = 0, y0 = 0, r0 = 0, r = rpie,
                   start = start_angle, end = end_angle, fill = Volume)) +
  geom_text(aes(x = rlabel*sin(mid_angle), y = rlabel*cos(mid_angle), label = Cnt),
            hjust = 0.5, vjust = 0.5) +
  coord_fixed() +
  scale_x_continuous(limits = c(-1, 1), name = "", breaks = NULL, labels = NULL) +
  scale_y_continuous(limits = c(-1, 1), name = "", breaks = NULL, labels = NULL) +
  facet_grid(Channel~.)

为了说明为什么我认为这这种做法是这样比传统的(更强大coord_polar()的方式,让我们说,我们要的馅饼,而不是内部的外部的标签。 这就产生了几个问题,比如我们将不得不调整hjustvjust取决于标签落下的馅饼一边,我们也将不得不做出的情节面板比高宽,以腾出空间一侧的标签而不产生的上方和下方空间过度。 在极坐标法求解这些问题不好玩,但它是在直角坐标系琐碎:

# generate hjust and vjust settings depending on the quadrant into which each
# label falls
dat_pies <- mutate(dat_pies,
                   hjust = ifelse(mid_angle>pi, 1, 0),
                   vjust = ifelse(mid_angle<pi/2 | mid_angle>3*pi/2, 0, 1))

rlabel = 1.05 * rpie # now we place labels outside of the pies

ggplot(dat_pies) + 
  geom_arc_bar(aes(x0 = 0, y0 = 0, r0 = 0, r = rpie,
                   start = start_angle, end = end_angle, fill = Volume)) +
  geom_text(aes(x = rlabel*sin(mid_angle), y = rlabel*cos(mid_angle), label = Cnt,
                hjust = hjust, vjust = vjust)) +
  coord_fixed() +
  scale_x_continuous(limits = c(-1.5, 1.4), name = "", breaks = NULL, labels = NULL) +
  scale_y_continuous(limits = c(-1, 1), name = "", breaks = NULL, labels = NULL) +
  facet_grid(Channel~.)



Answer 3:

要调整相对于坐标标签文本的位置,你可以使用vjusthjust的参数geom_text 。 这将决定同时所有标签的位置,所以这可能不是你所需要的。

或者,你可以调整标签的坐标。 定义一个新的data.frame ,你平均化Cnt坐标( label_x[i] = Cnt[i+1] + Cnt[i]来定位在该特定馅饼的中心的标签。 只是通过这个新的data.framegeom_text替换原来的data.frame

此外,有扇形图一些视觉解释的缺陷。 一般来说,我不会使用它们,尤其是在良好的替代品存在,如点阵图:

ggplot(dat, aes(x = Cnt, y = Volume)) + 
  geom_point() + 
  facet_wrap(~ Channel, ncol = 1)

例如,从这个图很明显, Cnt是亭比代理更高,这个信息在饼图丢失。



Answer 4:

以下的答案必须是局部的,笨重,我不会接受它。 希望的是,它会征求更好的解决方案。

text_KIOSK = dat$Cnt
text_AGENT = dat$Cnt
text_KIOSK[dat$Channel=='AGENT'] = 0
text_AGENT[dat$Channel=='KIOSK'] = 0
text_KIOSK = text_KIOSK/1.7 + c(0,cumsum(text_KIOSK)[-length(dat$Cnt)])
text_AGENT = text_AGENT/1.7 + c(0,cumsum(text_AGENT)[-length(dat$Cnt)])
text_KIOSK[dat$Channel=='AGENT'] = 0
text_AGENT[dat$Channel=='KIOSK'] = 0
pie_text = text_KIOSK + text_AGENT


vis = ggplot(data=dat, aes(x=factor(1), y=Cnt, fill=Volume)) +
  geom_bar(stat="identity", position=position_fill(width=1)) +
  coord_polar(theta="y") +
  facet_grid(Channel~.) +
  geom_text(aes(y=pie_text, label=format(Cnt,format="d",big.mark=','), ymax=Inf), position=position_fill(width=1))

它产生如下图所示:

当你发现我不能为绿色(低)移动标签。



文章来源: ggplot, facet, piechart: placing text in the middle of pie chart slices