Comment faire un scénario sunburst en R ou en Python?
7 réponses
version Python du diagramme de sunburst utilisant des barres matplotlib dans la 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 construire 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 au-dessus d'elle, la magie se produit:
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 coup de soleil en utilisant geom_tile
ggplot2
paquet. Commençons par créer 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 ensuite créer l'intrigue matricielle. Ici, le x
l'axe de la placette est couplé au x
variable dat
, le y
axe y
variable, et le remplissage des pixels à l' z
variable. Cela donne les courbes ci-dessous:
p = ggplot(dat, aes(x = x, y = y, fill = z)) + geom_tile()
print(p)
le ggplot2
package supporte toutes sortes de transformations de coordonnées, dont l'une prend un axe et le projette sur un cercle, c'est-à-dire des coordonnées polaires:
p + coord_polar()
Ce à peu près fait ce que vous avez besoin, maintenant, vous pouvez modifier dat
pour obtenir le résultat souhaité.
Theres un paquet appelé ggsunburst
. Malheureusement N'est pas dans CRAN mais vous pouvez installer en suivant les instructions sur le site web:http://genome.crg.es/~didac/ggsunburst/ggsunburst.html.
J'espère que cela aidera les gens qui sont encore à la recherche d'un bon paquet comme celui-ci.
Cordialement,
Il ya seulement un couple de bibliothèques que je sais de qui ne ce mode natif:
- Javascript Infovis Toolkit (jit) (exemple).
- D3.js
- Ocaml's Tracé Simple Outil (SPT).
aucun de ceux-ci ne sont en Python ou R, mais obtenir un script python/R pour écrire un simple fichier JSON qui peut être chargé par l'une ou l'autre des bibliothèques javascript devrait être joli. réalisable.
Voici un ggplot2
Coup de soleil avec deux couches.
L'idée de base est de faire juste un bar différent pour chaque couche, et de faire les barres plus larges pour les couches extérieures. J'ai aussi trafiqué avec l'axe des abscisses pour m'assurer qu'il n'y a pas de trou au milieu du diagramme circulaire interne. Vous pouvez ainsi contrôler l'apparence du sunburst en changeant les valeurs de la largeur et de l'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 à sunburst-logiciel spécifique, c'est qu'il suppose que vous voulez que les couches extérieures à être exhaustifs (aucun espace). Les couches externes "partiellement exhaustives" (comme dans d'autres exemples) sont certainement possibles mais plus compliquées.
pour plus d'exhaustivité, ici, il est nettoyé avec un plus beau formatage et des étiquettes:
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())
depuis jbkunst mentionné ggsunburst, ici je poste un exemple pour reproduire le sunburst par sirex.
Ce n'est pas exactement le même, parce que dans ggsunburst l'angle d'un nœud est égale à 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)