我被要求重新创建以下风格的情节。 (请忽略这是否是一种良好的可视化类型的问题,并将此视为将数字表添加到数字表中。)
大部分内容非常简单,但我还没有找到一个让中心空洞的好方法。为了节省时间,我可能会采用添加隐形虚拟数据的方法(如果没有其他人这样做,我会发布该方法,但它似乎不如修改主题的方法更优化)。是否有基于主题的解决方案或非ggplot2 R解决方案?
library(ggplot2)
# make sample dataframe
Category <- c("Electronics", "Appliances", "Books", "Music", "Clothing",
"Cars", "Food/Beverages", "Personal Hygiene",
"Personal Health/OTC", "Hair Care")
Percent <- c(81, 77, 70, 69, 69, 68, 62, 62, 61, 60)
internetImportance<-data.frame(Category,Percent)
# append number to category name
internetImportance$Category <-
paste0(internetImportance$Category," - ",internetImportance$Percent,"%")
# set factor so it will plot in descending order
internetImportance$Category <-
factor(internetImportance$Category,
levels=rev(internetImportance$Category))
# plot
ggplot(internetImportance, aes(x = Category, y = Percent,
fill = Category)) +
geom_bar(width = 0.9, stat="identity") +
coord_polar(theta = "y") +
xlab("") + ylab("") +
ylim(c(0,100)) +
ggtitle("Top Product Categories Influenced by Internet") +
geom_text(data = internetImportance, hjust = 1, size = 3,
aes(x = Category, y = 0, label = Category)) +
theme_minimal() +
theme(legend.position = "none",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_blank(),
axis.ticks = element_blank())
我们如何用空心中心绘制这些数据?
答案 0 :(得分:27)
这是一个使用plotrix
包的非ggplot2(基础R图形)解决方案,它包含两个不错的功能:draw.circle()
和draw.arc()
:
circBarPlot <- function(x, labels, colors=rainbow(length(x)), cex.lab=1) {
require(plotrix)
plot(0,xlim=c(-1.1,1.1),ylim=c(-1.1,1.1),type="n",axes=F, xlab=NA, ylab=NA)
radii <- seq(1, 0.3, length.out=length(x))
draw.circle(0,0,radii,border="lightgrey")
angles <- (1/4 - x)*2*pi
draw.arc(0, 0, radii, angles, pi/2, col=colors, lwd=130/length(x), lend=2, n=100)
ymult <- (par("usr")[4]-par("usr")[3])/(par("usr")[2]-par("usr")[1])*par("pin")[1]/par("pin")[2]
text(x=-0.02, y=radii*ymult, labels=paste(labels," - ", x*100, "%", sep=""), pos=2, cex=cex.lab)
}
circBarPlot(Percent/100, Category)
text(0,0,"GLOBAL",cex=1.5,col="grey")
它给了我:
答案 1 :(得分:22)
我认为立即修复是创建一些“空”条目。我会像这样创建internetImportance
data.frame:
Category <- c("Electronics", "Appliances", "Books", "Music", "Clothing",
"Cars", "Food/Beverages", "Personal Hygiene",
"Personal Health/OTC", "Hair Care")
Percent <- c(81, 77, 70, 69, 69, 68, 62, 62, 61, 60)
internetImportance <- data.frame(Category,Percent)
len <- 4
df2 <- data.frame(Category = letters[1:len], Percent = rep(0, len),
Category2 = rep("", len))
internetImportance$Category2 <-
paste0(internetImportance$Category," - ",internetImportance$Percent,"%")
# append number to category name
internetImportance <- rbind(internetImportance, df2)
# set factor so it will plot in descending order
internetImportance$Category <-
factor(internetImportance$Category,
levels=rev(internetImportance$Category))
然后我将ggplot2
与fill=category2
联系起来,如下所示:
ggplot(internetImportance, aes(x = Category, y = Percent,
fill = Category2)) +
geom_bar(width = 0.9, stat="identity") +
coord_polar(theta = "y") +
xlab("") + ylab("") +
ylim(c(0,100)) +
ggtitle("Top Product Categories Influenced by Internet") +
geom_text(data = internetImportance, hjust = 1, size = 3,
aes(x = Category, y = 0, label = Category2)) +
theme_minimal() +
theme(legend.position = "none",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_blank(),
axis.ticks = element_blank())
这给了我:
您可以在geom_text(label="GLOBAL", x=.5, y=.5, size=4) +
之前添加theme_minimal
来添加文字GLOBAL
。
答案 2 :(得分:12)
另一个不依赖base
包的plotrix
解决方案:
circular.barplot<-function(values, labels, col, cex){
df<-data.frame(values=sort(values), labels=labels[order(values)])
col<-col[order(values)]
plot(NA,xlim=c(-1.3,1.3),ylim=c(-1.3,1.3),axes=F, xlab=NA, ylab=NA, asp=1)
t<-sapply(df$values,function(x).5*pi-seq(0, 2*pi*x/100,length=1000))
x<-sapply(1:nrow(df),function(x)(.3+x/nrow(df))*cos(t[,x]))
y<-sapply(1:nrow(df),function(x)(.3+x/nrow(df))*sin(t[,x]))
for(i in 1:nrow(df)){
lines(x=x[,i],y=y[,i],col=col[i],lwd=10,lend=1)
text(x[1,i],y[1,i],paste(df$labels[i]," - ",df$values[i],"%",sep=""),
pos=2,cex=cex)
}
}
答案 3 :(得分:2)
由于图是圆形的,因此可以通过circlize
包轻松完成。
首先是数据:
Category <- c("Electronics", "Appliances", "Books", "Music", "Clothing",
"Cars", "Food/Beverages", "Personal Hygiene",
"Personal Health/OTC", "Hair Care")
Percent <- c(81, 77, 70, 69, 69, 68, 62, 62, 61, 60)
color = rainbow(length(Percent))
反转三个向量,因为circlize
默认情况下将每个元素从内部添加到外部:
Category = rev(Category)
Percent = rev(Percent)
color = rev(color)
如果你想象的是圆形是一个弯曲的绘图区域,那么它只是添加了矩形,线条和文本。
library(circlize)
par(mar = c(1, 1, 1, 1))
circos.par("start.degree" = 90)
circos.initialize("a", xlim = c(0, 100)) # 'a` just means there is one sector
circos.trackPlotRegion(ylim = c(0.5, length(Percent)+0.5), track.height = 0.8,
bg.border = NA, panel.fun = function(x, y) {
xlim = get.cell.meta.data("xlim") # in fact, it is c(0, 100)
for(i in seq_along(Percent)) {
circos.lines(xlim, c(i, i), col = "#CCCCCC")
circos.rect(0, i - 0.45, Percent[i], i + 0.45, col = color[i],
border = "white")
circos.text(xlim[2], i, paste0(Category[i], " - ", Percent[i], "%"),
adj = c(1, 0.5))
}
})
circos.clear()
text(0, 0, "GLOBAL", col = "#CCCCCC")