如何在 R 或 Python 中制作旭日图?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12926779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make a sunburst plot in R or Python?
提问by dmvianna
So far I have been unable to find an R library that can create a sunburst plot like those by John Stasko. Anyone knows how to accomplish that in R or Python?
到目前为止,我一直无法找到可以创建像John Stasko那样的旭日图的 R 库。任何人都知道如何在 R 或 Python 中实现它?


采纳答案by sirex
Python version of sunburst diagram using matplotlib bars in polar projection:
在极坐标投影中使用 matplotlib 条的森伯斯特图的 Python 版本:
import numpy as np
import matplotlib.pyplot as plt
def sunburst(nodes, total=np.pi * 2, offset=0, level=0, ax=None):
ax = ax or plt.subplot(111, projection='polar')
if level == 0 and len(nodes) == 1:
label, value, subnodes = nodes[0]
ax.bar([0], [0.5], [np.pi * 2])
ax.text(0, 0, label, ha='center', va='center')
sunburst(subnodes, total=value, level=level + 1, ax=ax)
elif nodes:
d = np.pi * 2 / total
labels = []
widths = []
local_offset = offset
for label, value, subnodes in nodes:
labels.append(label)
widths.append(value * d)
sunburst(subnodes, total=total, offset=local_offset,
level=level + 1, ax=ax)
local_offset += value
values = np.cumsum([offset * d] + widths[:-1])
heights = [1] * len(nodes)
bottoms = np.zeros(len(nodes)) + level - 0.5
rects = ax.bar(values, heights, widths, bottoms, linewidth=1,
edgecolor='white', align='edge')
for rect, label in zip(rects, labels):
x = rect.get_x() + rect.get_width() / 2
y = rect.get_y() + rect.get_height() / 2
rotation = (90 + (360 - np.degrees(x) % 180)) % 360
ax.text(x, y, label, rotation=rotation, ha='center', va='center')
if level == 0:
ax.set_theta_direction(-1)
ax.set_theta_zero_location('N')
ax.set_axis_off()
Example, how this function can be used:
示例,如何使用此函数:
data = [
('/', 100, [
('home', 70, [
('Images', 40, []),
('Videos', 20, []),
('Documents', 5, []),
]),
('usr', 15, [
('src', 6, [
('linux-headers', 4, []),
('virtualbox', 1, []),
]),
('lib', 4, []),
('share', 2, []),
('bin', 1, []),
('local', 1, []),
('include', 1, []),
]),
]),
]
sunburst(data)
回答by John Lyon
There are only a couple of libraries that I know of that do this natively:
我所知道的只有几个库可以本地执行此操作:
- The Javascript Infovis Toolkit(jit) (example).
- D3.js
- OCaml's Simple Plot Tool(SPT).
- 所述的Javascript Infovis工具包(JIT)(例如)。
- D3.js
- OCaml 的简单绘图工具(SPT)。
Neither of these are in Python or R, but getting a python/R script to write out a simple JSON file that can be loaded by either of the javascript libraries should be pretty achievable.
这些都不是在 Python 或 R 中,但是获得一个 python/R 脚本来写出一个可以由任何一个 javascript 库加载的简单 JSON 文件应该是可以实现的。
回答by Paul Hiemstra
You can create something along the lines of a sunburst plot using geom_tilefrom the ggplot2package. Let's first create some random data:
您可以使用geom_tilefromggplot2包沿着旭日图的线条创建一些东西。让我们首先创建一些随机数据:
require(ggplot2); theme_set(theme_bw())
require(plyr)
dat = data.frame(expand.grid(x = 1:10, y = 1:10),
z = sample(LETTERS[1:3], size = 100, replace = TRUE))
And then create the raster plot. Here, the xaxis in the plot is coupled to the xvariable in dat, the yaxis to the yvariable, and the fill of the pixels to the zvariable. This yields the following plot:
然后创建光栅图。这里,图中的x轴与x变量 in耦合dat,y轴与y变量耦合,像素的填充与变量耦合z。这产生了以下情节:
p = ggplot(dat, aes(x = x, y = y, fill = z)) + geom_tile()
print(p)


The ggplot2package supports all kinds of coordinate transformations, one of which takes one axis and projects it on a circle, i.e. polar coordinates:
该ggplot2包支持各种坐标变换,其中一种是取一个轴并将其投影到一个圆上,即极坐标:
p + coord_polar()


This roughly does what you need, now you can tweak datto get the desired result.
这大致可以满足您的需求,现在您可以进行调整dat以获得所需的结果。
回答by jbkunst
Theres a package called ggsunburst. Sadly is not in CRAN but you can install following the instruction in the website: http://genome.crg.es/~didac/ggsunburst/ggsunburst.html.
有一个名为ggsunburst. 遗憾的是不在 CRAN 中,但您可以按照网站中的说明进行安装:http: //genome.crg.es/~didac/ggsunburst/ggsunburst.html。
Hope it helps to people who still looking for a good package like this.
希望它对仍在寻找这样的好包的人有所帮助。
Regards,
问候,
回答by vonjd
You can even build an interactive version quite easily with R now:
您现在甚至可以使用 R 轻松构建交互式版本:
# devtools::install_github("timelyportfolio/sunburstR")
library(sunburstR)
# read in sample visit-sequences.csv data provided in source
# https://gist.github.com/kerryrodden/7090426#file-visit-sequences-csv
sequences <- read.csv(
system.file("examples/visit-sequences.csv",package="sunburstR")
,header=F
,stringsAsFactors = FALSE
)
sunburst(sequences)
...and when you move your mouse above it, the magic happens:
...当你将鼠标移到它上面时,神奇的事情发生了:
Edit
The official site of this package can be found here (with many examples!): https://github.com/timelyportfolio/sunburstR
编辑
这个包的官方网站可以在这里找到(有很多例子!):https: //github.com/timelyportfolio/sunburstR
Hat Tip to @timelyportfolio who created this impressive piece of code!
给@timelyportfolio 的帽子提示,他创造了这段令人印象深刻的代码!
回答by dmp
Here's a ggplot2sunburst with two layers.
这是一个ggplot2有两层的旭日。
The basic idea is to just make a different bar for each layer, and make the bars wider for the outer layers. I also messed with the x-axis to make sure there's no hole in the middle of the inner pie chart. You can thus control the look of the sunburst by changing the width and x-axis values.
基本思想是为每一层制作不同的条形,并为外层制作更宽的条形。我还弄乱了 x 轴,以确保内部饼图的中间没有洞。因此,您可以通过更改宽度和 x 轴值来控制旭日形的外观。
library(ggplot2)
# make some fake data
df <- data.frame(
'level1'=c('a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c'),
'level2'=c('a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'c1', 'c2', 'c3'),
'value'=c(.025, .05, .027, .005, .012, .014, .1, .03, .18))
# sunburst plot
ggplot(df, aes(y=value)) +
geom_bar(aes(fill=level1, x=0), width=.5, stat='identity') +
geom_bar(aes(fill=level2, x=.25), width=.25, stat='identity') +
coord_polar(theta='y')
The only disadvantage this has compared to sunburst-specific software is that it assumes you want the outer layers to be collectively exhaustive (i.e. no gaps). "Partially exhaustive" outer layers (like in some of the other examples) are surely possible but more complicated.
与特定于 sunburst 的软件相比,它的唯一缺点是它假设您希望外层整体详尽(即没有间隙)。“部分详尽”的外层(如在其他一些示例中)当然是可能的,但更复杂。
For completeness, here it is cleaned up with nicer formatting and labels:
为了完整起见,这里用更好的格式和标签进行了清理:
library(data.table)
# compute cumulative sum for outer labels
df <- data.table(df)
df[, cumulative:=cumsum(value)-(value/2)]
# store labels for inner circle
inner_df <- df[, c('level1', 'value'), with=FALSE]
inner_df[, level1_value:=sum(value), by='level1']
inner_df <- unique(text_df[, c('level1', 'level1_value'), with=FALSE])
inner_df[, cumulative:=cumsum(level1_value)]
inner_df[, prev:=shift(cumulative)]
inner_df[is.na(prev), position:=(level1_value/2)]
inner_df[!is.na(prev), position:=(level1_value/2)+prev]
colors <- c('#6a3d9a', '#1F78B4', '#33A02C', '#3F146D', '#56238D', '#855CB1', '#AD8CD0', '#08619A', '#3F8DC0', '#076302', '#1B8416', '#50B74B')
colorNames <- c(unique(as.character(df$level1)), unique(as.character(df$level2)))
names(colors) <- colorNames
ggplot(df, aes(y=value, x='')) +
geom_bar(aes(fill=level2, x=.25), width=.25, stat='identity') +
geom_bar(aes(fill=level1, x=0), width=.5, stat='identity') +
geom_text(data=inner_df, aes(label=level1, x=.05, y=position)) +
coord_polar(theta='y') +
scale_fill_manual('', values=colors) +
theme_minimal() +
guides(fill=guide_legend(ncol=1)) +
labs(title='') +
scale_x_continuous(breaks=NULL) +
scale_y_continuous(breaks=df$cumulative, labels=df$level2, 5) +
theme(axis.title.x=element_blank(), axis.title.y=element_blank(), panel.border=element_blank(), panel.grid=element_blank())
回答by didac
Since jbkunst mentioned ggsunburst, here I post an example for reproducing the sunburst by sirex.
既然jbkunst提到了ggsunburst,这里我贴一个用sirex重现sunburst的例子。
It is not exactly the same because in ggsunburst the angle of a node is equal to the sum of the angles of its children nodes.
它并不完全相同,因为在 ggsunburst 中,节点的角度等于其子节点的角度之和。
# install ggsunburst package
if (!require("ggplot2")) install.packages("ggplot2")
if (!require("rPython")) install.packages("rPython")
install.packages("http://genome.crg.es/~didac/ggsunburst/ggsunburst_0.0.9.tar.gz", repos=NULL, type="source")
library(ggsunburst)
# dataframe
# each row corresponds to a node in the hierarchy
# parent and node are required, the rest are optional attributes
# the attributes correspond to the node, not its parent
df <- read.table(header = T, sep = ",", text = "
parent,node,size,color,dist
,/,,B,1
/,home,,D,1
home,Images, 40,E,1
home,Videos, 20,E,1
home,Documents, 5,E,1
/,usr,,D,1
usr,src,,A,1
src,linux-headers, 4,C,1.5
src,virtualbox, 1,C,1.5
usr,lib, 4,A,1
usr,share, 2,A,1
usr,bin, 1,A,1
usr,local, 1,A,1
usr,include, 1,A,1
")
write.table(df, 'df.csv', sep = ",", row.names = F)
# compute coordinates from dataframe
# "node_attributes" is used to pass the attributes other than "size" and "dist",
# which are special attributes that alter the dimensions of the nodes
sb <- sunburst_data('df.csv', sep = ",", type = "node_parent", node_attributes = "color")
# plot
sunburst(sb, node_labels = T, node_labels.min = 10, rects.fill.aes = "color") +
scale_fill_brewer(palette = "Set1", guide = F)

