【问题标题】:Circular plot in ggplot2 with line segments connected in rggplot2中的圆形图,线段在r中连接
【发布时间】:2012-07-25 01:06:22
【问题描述】:

我正在尝试创建一个圆形图并卡在一个点:

dat1 <- data.frame (xvar = 1:10, y = 6, ymin = 4, ymax = 4.5)

使用这些数据,我可以在 ggplot2 中生成圆形带状图

require(ggplot2) 
 ggplot(dat1, aes(x=xvar, y=y)) +  geom_ribbon(aes(ymin=ymin, ymax=ymax),
  col = "blue", fill = "blue2") + ylim (c(0,6)) + coord_polar()

但是我想要更多。

我想使用以下数据用不同的颜色和标签填充功能区的片段。

 filld <- data.frame (start = c(1, 4, 6, 7.5, 8, 9), end = c(4, 6, 7.5, 8, 9, 10),
                         label = c("A", "B", "C", "A", "C", "D"))
  filld
##    start  end label
## 1   1.0  4.0     A
## 2   4.0  6.0     B
## 3   6.0  7.5     C
## 4   7.5  8.0     A
## 5   8.0  9.0     C
## 6   9.0 10.0     D

功能区将根据标签变量填充不同的颜色。例如,段 A 将从 1 开始并在 4 结束。然后段 B 将从 6 开始和结束并填充不同的颜色。具有相同标签的段(例如 A 和 C)将按线连接。

生成的图将如下所示:

【问题讨论】:

  • 漂亮的图表 :) 添加抗锯齿效果很棒

标签: r ggplot2


【解决方案1】:

这是一个例子:

filld$p <- rowMeans(subset(filld, select = c(start, end)))
ggplot(filld, aes(xmin = start, xmax = end, ymin = 4, ymax = 5, fill = label)) + 
  geom_rect() + 
  geom_segment(data = subset(filld, label %in% label[duplicated(label)]),
               aes(x = p, y = 0, xend = p, yend = 4, colour = label),
               size = 2, show_guide = FALSE) +
  geom_text(aes(x = p, y = 4.5, label = label), colour = "white", size = 10) +
  coord_polar() + 
  scale_y_continuous(limits = c(0, 5))

更新

我不建议这样做:

filld <- data.frame (start = c(1, 4, 6, 7.5, 8, 9), end = c(4, 6, 7.5, 8, 9, 10),
                     label = c("A", "B", "C", "A", "C", "D"))
filld$p <- rowMeans(subset(filld, select = c(start, end)))
filld <- merge(filld, ddply(filld, .(label), summarize, p2 = mean(p)))

lnd <- subset(filld, label %in% label[duplicated(label)])
lnd <- ddply(lnd, .(label), function(x) {
  x <- seq(x$p[1], x$p[2], length = 100)
  y <- 4.5 + ((x - mean(x))^2 - (x[1]-mean(x))^2) / (x[1]-mean(x))^2 * 3 + sin(x*3*pi) * 0.1
  data.frame(x, y)
})


p <- ggplot(filld, aes(xmin = start, xmax = end, ymin = 4, ymax = 5, colour = label, fill = label)) + 
  geom_line(aes(x, y, xmin = NULL, ymin = NULL, xmax = NULL, ymax = NULL), data = lnd, size = 2) +
  geom_rect() + 
  geom_text(aes(x = p, y = 4.5, label = label), colour = "white", size = 10) +
  coord_polar() + 
  scale_y_continuous(limits = c(0, 5))
p

也许,你想要的超出了ggplot2的范围。

【讨论】:

  • @kohske 相当不错......线条要好得多,但我想知道是否有可能制作低于 180 的线条来制作更小的循环,以便通过中心连接线条以避免拥挤跨度>
  • 我在想p + annotation_custom(gridExtra::arcTextGrob()),但遗憾的是它与极坐标不兼容。也许它应该只是一个警告。
  • 可能有一个 geom_arc 与相关的统计数据,它的工作方式类似于 geom_segment,但从不咀嚼,并将成对的观察与 curveGrob 连接起来
  • 很酷的例子,让我想起了circos diagrams。尽管我对几何的掌握还不够强,但无法就如何在极坐标中绘制此类弧线提出建议。这是d3.js 中的另一个示例。编辑 - 我看到 Paolo's answer 也给出了一个非常相似的例子。
  • 不幸的是 circos 是 perl 并且我在 R 中找不到类似质量的 r 包。
【解决方案2】:

看看ggbio。这个包将 ggplot2 和图形语法扩展到序列数据(生物信息学),但它们似乎解决了您的问题(例如,参见 here)。查看软件包的 source code 可能会引导您找到更通用的解决方案。

【讨论】:

    【解决方案3】:

    添加ymin等填充d

    fd <- data.frame(filld, ymin = 4, y =6, ymax = 4.5)
    

    然后使用geom_rect 与列label 作为fillcolour 美学

     ggplot(fd, aes(x=start,xmin = start, xmax = end, y=y)) +  
       geom_rect(aes(ymin=ymin, ymax=ymax, fill = label )) + 
       ylim (c(0,6)) + 
       coord_polar() 
    

    添加行:

    ## calculate the midpoint for each segment
    fd$xmid <- apply(fd[,1:2],1,mean)
    ## get the replicate id for the labels (what occurence is this)
    library(plyr)
    library(reshape2)
    fd1 <- ddply(fd, .(label), mutate, id = 1:length(xmid))
    ## reshape to wide, subsetting only with more than one rep
    .lines <- na.omit(dcast(fd1, label~id, value.var = 'xmid'))
    ## add a mid point between the mid points
    .lines$mid <- apply(.lines[,2:3],1,mean)
    ## reshape to long, and add some y values 
    ld <- data.frame(arrange(melt(.lines,value.name = 'x'), label, x), y = rep(c(4,3,4),2))
    
    ggplot(fd) +  
      geom_rect(aes(x=start,xmin = start, xmax = end, y=y,ymin=ymin, ymax=ymax, fill = label )) + 
      ylim (c(0,6)) + 
      coord_polar() + geom_path(data = ld, aes(x=x,y=y,colour = label))
    

    线条很丑,但在那里!

    【讨论】: