Jusqu'à présent, je n'ai pas pu trouver une bibliothèque R qui puisse créer un tracé sunburst comme ceux-ci par John Stasko . Quelqu'un sait comment accomplir cela en R ou en Python?
Version Python du diagramme sunburst utilisant des barres matplotlib en projection polaire:
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()
Exemple, comment cette fonction peut être utilisée:
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)
Vous pouvez même créer une version interactive assez facilement avec R maintenant:
# 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)
... et lorsque vous déplacez votre souris dessus, la magie opère:
Modifier
Le site officiel de ce package peut être trouvé ici (avec de nombreux exemples!): https://github.com/timelyportfolio/sunburstR
Pointe du chapeau à @timelyportfolio qui a créé cet impressionnant morceau de code!
Vous pouvez créer quelque chose comme un tracé sunburst en utilisant geom_tile
du ggplot2
paquet. Créons d'abord des données aléatoires:
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))
Et puis créez le tracé raster. Ici, l'axe x
dans le graphique est couplé à la variable x
dans dat
, l'axe y
à la variable y
, et le remplissage des pixels à la variable z
. Cela donne le graphique suivant:
p = ggplot(dat, aes(x = x, y = y, fill = z)) + geom_tile()
print(p)
Le ggplot2
le package prend en charge toutes sortes de transformations de coordonnées, dont l'une prend un axe et la projette sur un cercle, c'est-à-dire les coordonnées polaires:
p + coord_polar()
Cela fait à peu près ce dont vous avez besoin, vous pouvez maintenant Tweak dat
pour obtenir le résultat souhaité.
Il y a un paquet appelé ggsunburst
. Malheureusement, il n'est pas dans CRAN, mais vous pouvez l'installer en suivant les instructions du site Web: http://genome.crg.es/~didac/ggsunburst/ggsunburst.html .
J'espère que cela aide les personnes qui recherchent toujours un bon forfait comme celui-ci.
Cordialement,
Voici un ggplot2
sunburst avec deux couches.
L'idée de base est de simplement créer une barre différente pour chaque couche et d'agrandir les barres pour les couches externes. J'ai également joué avec l'axe des x pour m'assurer qu'il n'y a pas de trou au milieu du graphique à secteurs interne. Vous pouvez ainsi contrôler l'apparence du sunburst en modifiant les valeurs de largeur et d'axe des 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')
Le seul inconvénient que cela a par rapport aux logiciels spécifiques à Sunburst est qu'il suppose que vous voulez que les couches externes soient collectivement exhaustives (c'est-à-dire sans lacunes). Des couches externes "partiellement exhaustives" (comme dans certains des autres exemples) sont sûrement possibles mais plus compliquées.
Pour être complet, ici, il est nettoyé avec un formatage et des étiquettes plus agréables:
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())
Il n'y a que quelques bibliothèques que je connais qui le font nativement:
Aucun de ces éléments n'est en Python ou R, mais obtenir un script python/R pour écrire un simple fichier JSON qui peut être chargé par l'une des bibliothèques javascript devrait être assez réalisable.
Puisque jbkunst a mentionné ggsunburst, je poste ici un exemple de reproduction du sunburst par sirex.
Ce n'est pas exactement la même chose car dans ggsunburst, l'angle d'un nœud est égal à la somme des angles de ses nœuds enfants.
# 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)