top*_*hef 18 visualization r facet ggplot2 pie-chart
我正在尝试使用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))
Run Code Online (Sandbox Code Playgroud)
输出:

geom_text应该调整哪些参数才能将数字标签放在饼图切片的中间?
相关问题是Pie plot将其文本放在彼此的顶部,但它不处理facet的情况.
更新:在上面的问题中遵循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))
Run Code Online (Sandbox Code Playgroud)
正如我所预期的那样调整coordiantes是绝对的,但它需要在facet数据中:

Jaa*_*aap 36
新的答案:随着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")
Run Code Online (Sandbox Code Playgroud)
要删除"空心"中心,请将代码调整为:
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")
Run Code Online (Sandbox Code Playgroud)
老答案:这个问题的解决方案是创建一个位置变量,可以使用base R或data.table,plyr或dplyr包很容易地完成:
第1步:为每个Channel创建位置变量
# 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)
Run Code Online (Sandbox Code Playgroud)
第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")
Run Code Online (Sandbox Code Playgroud)
结果:

Cla*_*lke 14
我想反对在ggplot2中制作馅饼的传统方法,即在极坐标中绘制堆积的条形图.虽然我很欣赏这种方法的数学优雅,但当情节看起来不像预期时,它会引起各种各样的麻烦.特别是,精确调整馅饼的大小可能很困难.(如果您不知道我的意思,请尝试制作一个延伸到绘图面板边缘的饼图.)
我更喜欢使用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)
Run Code Online (Sandbox Code Playgroud)
饼图代码:
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~.)
Run Code Online (Sandbox Code Playgroud)
为了说明为什么我认为这种方法比传统(coord_polar())方法更强大,让我们说我们希望标签位于饼外而不是内部.这会产生一些问题,例如我们将不得不进行调整,hjust并vjust根据标签所在的饼图边缘进行调整,并且我们还必须使绘图面板宽于高,以便为侧面的标签腾出空间而不生成上下空间过大.在极坐标方法中解决这些问题并不好玩,但在笛卡尔坐标中它是微不足道的:
# 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~.)
Run Code Online (Sandbox Code Playgroud)
要调整标签文本相对于坐标的位置,可以使用vjust和的hjust参数geom_text.这将同时确定所有标签的位置,因此这可能不是您所需要的.
或者,您可以调整标签的坐标.定义一个新的data.frame平均Cnt坐标(label_x[i] = Cnt[i+1] + Cnt[i]),将标签定位在该特定饼图的中心.只是通过这个新data.frame来geom_text替换原来的data.frame.
此外,饼图有一些视觉解释缺陷.一般来说,我不会使用它们,尤其是存在良好替代品的地方,例如点图:
ggplot(dat, aes(x = Cnt, y = Volume)) +
geom_point() +
facet_wrap(~ Channel, ncol = 1)
Run Code Online (Sandbox Code Playgroud)
例如,从这个图中可以看出Cnt,Kiosk比代理更高,这个信息在饼图中丢失了.

| 归档时间: |
|
| 查看次数: |
18457 次 |
| 最近记录: |