GGTRAP,刻面,PyCART:在饼图切片中间放置文本 我试图用GGPrice制作一个面饼图,并在每个切片中间放置文本的问题: 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))

GGTRAP,刻面,PyCART:在饼图切片中间放置文本 我试图用GGPrice制作一个面饼图,并在每个切片中间放置文本的问题: 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)),r,ggplot2,visualization,pie-chart,facet,R,Ggplot2,Visualization,Pie Chart,Facet,输出: 代码> GEOMUX文本应调整哪些参数以将数字标签放置在PeCube切片的中间? 相关的问题是,但它不处理方面的情况 更新:根据Paul 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)) + g

输出:

<>代码> GEOMUX文本<代码>应调整哪些参数以将数字标签放置在PeCube切片的中间?

相关的问题是,但它不处理方面的情况

更新:根据Paul 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))
正如我所料,调整文本坐标是绝对的,但它需要在方面数据内:

要调整标签文本相对于坐标的位置,可以使用
geom\u text
vjust
hjust
参数。这将同时确定所有标签的位置,因此这可能不是您所需要的

或者,可以调整标签的坐标。定义一个新的
data.frame
,在其中平均
Cnt
坐标(
label\u x[i]=Cnt[i+1]+Cnt[i]
),将标签定位在该特定饼图的中心。只需将新的
data.frame
传递给
geom\u text
,以替换原来的
data.frame

此外,图表还存在一些视觉解释缺陷。一般来说,我不会使用它们,尤其是在存在良好替代方案的情况下,例如点图:

ggplot(dat, aes(x = Cnt, y = Volume)) + 
  geom_point() + 
  facet_wrap(~ Channel, ncol = 1)
例如,从该图可以明显看出,Kiosk的Cnt比代理的Cnt高,该信息在图表中丢失


下面的答案是片面的、笨拙的,我不会接受。 希望它能寻求更好的解决方案

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))
它生成以下图表:


正如您所注意到的,我无法移动绿色(低)标签。

新答案:随着ggplot2 v2.2.0的引入,
position\u 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")

旧答案:此问题的解决方案是创建一个位置变量,这可以很容易地使用base R或,或包来完成:

步骤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)
结果:


我想公开反对在ggplot2中制作馅饼的传统方法,即在极坐标系中绘制堆叠条形图。虽然我欣赏这种方法在数学上的优雅,但当情节看起来不太符合预期时,它确实会引起各种各样的麻烦。特别是,精确调整饼图的大小可能很困难。(如果您不知道我的意思,请尝试制作一个一直延伸到绘图面板边缘的饼图。)

我更喜欢在正常的笛卡尔坐标系中绘制派,使用ggforce的
geom\u arc\u bar()。这需要在前端做一点额外的工作,因为我们必须自己计算角度,但这很容易,因此我们得到的控制水平非常值得。
我在以前的回答和回答中使用过这种方法

数据(来自问题):

饼图代码:

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~.)

谢谢你的回答-我会试试看。但我不同意提议的地块是皮查特的替代品。在我看来,Cnt较高的事实主要是由于未对齐的文本标签而丢失的。饼图不能显示代理和KIOSK之间的大小差异,因为它只显示相对大小。在我看来,这篇课文更难理解。当比较(比如)5个类别时,这种影响会变得更大。像这样的书提倡使用点状图这样的图表,而倾向于使用柱状图。只需在谷歌上搜索
饼图邪恶
。不幸的是,这个答案并没有解决有刻面的问题,因为长度需要在刻面变量之间对齐。我不太确定你的意思。如果您需要面之间的相对大小,只需在调用
facet\u wrap
时使用
scale=free\u x
。我不使用fact\u wrap-我使用facet\u grid(在这种情况下,由于比例适用于两者,所以与此无关)。比例如何帮助对齐文本标签?我的意思是,饼图文本数字应该用相应的方面(可变通道)来计算。我对这个问题的最新解决方案是尽可能避免饼图:-)你看到我的答案了吗?我认为它提供了你所要求的解决方案。是的,谢谢。只要可能,我会坚持“不使用饼图”的原则,但对于例外情况,你的答案就是答案:-)你尽可能避免使用饼图是绝对正确的,但有些人似乎真的很喜欢它们。大多数情况下,结构良好的条形图更清晰。感谢您的最新帮助。有没有办法摆脱“空心”中心?(中间的白色小圆圈)@jesusgarciab可能有点晚了,但我已经更新了答案
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~.)
# 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~.)