簡體   English   中英

制作一個帶有空心圓形的圓形條形圖(又名賽道圖)

[英]Making a circular barplot with a hollow center (aka race track plot)

我被要求重新創建以下風格的情節。 (請忽略這是否是一種良好的可視化類型的問題,並將此視為在數字表中添加彩色元素。)

大部分都很簡單,但我還沒有找到一個讓中心空洞的好方法。 為了節省時間,我可能會采用添加隱形虛擬數據的方法(如果沒有其他人這樣做,我會發布該方法,但它似乎不如修改主題的方法更優化)。 是否有基於主題的解決方案或非ggplot2 R解決方案?

我們在模仿的是什么

在此輸入圖像描述

簡單的ggplot2結果(不需要的填充中心)

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())

在此輸入圖像描述

我們如何用空心中心繪制這些數據?

這是一個使用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")

它給了我:

圓形條形圖

我認為立即修復是創建一些“空”條目。 我會像這樣創建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))

然后我用fill=category2繪制ggplot2 ,如下所示:

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

另一個不依賴於plotrix包的base解決方案:

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)
        }
    }

在此輸入圖像描述

由於圖是圓形的,因此可以通過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")

在此輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM