如何在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:11:46  来源:igfitidea点击:

How to make a sunburst plot in R or Python?

pythonrggplot2data-visualizationsunburst-diagram

提问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 中实现它?

Sunburst

旭日

采纳答案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)

python matplotlib sunburst diagram

python matplotlib森伯斯特图

回答by John Lyon

There are only a couple of libraries that I know of that do this natively:

我所知道的只有几个库可以本地执行此操作:

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耦合daty轴与y变量耦合,像素的填充与变量耦合z。这产生了以下情节:

p = ggplot(dat, aes(x = x, y = y, fill = z)) + geom_tile() 
print(p)

enter image description here

在此处输入图片说明

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

enter image description here

在此处输入图片说明

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

enter image description here

在此处输入图片说明

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)

enter image description here

在此处输入图片说明

...and when you move your mouse above it, the magic happens:

...当你将鼠标移到它上面时,神奇的事情发生了:

enter image description here

在此处输入图片说明

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

enter image description here

在此处输入图片说明

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

enter image description here

在此处输入图片说明

回答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)

enter image description here

在此处输入图片说明