Jak zrobić wykres sunburst w R lub Pythonie?

Do tej pory nie udało mi się znaleźć biblioteki R, która mogłaby stworzyć fabułę sunburst jak te autorstwa Johna Staśko. Wie ktoś jak to osiągnąć w R lub Pythonie?

Sunburst

Author: VividD, 2012-10-17

7 answers

Wersja Pythona diagramu sunburst wykorzystującego paski matplotlib w projekcji biegunowej:

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

Przykład, jak można użyć tej funkcji:

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

 18
Author: sirex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-17 13:16:13

Możesz nawet łatwo zbudować interaktywną wersję za pomocą 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)

Tutaj wpisz opis obrazka

...a gdy przesuniesz mysz nad nią, dzieje się magia:

Tutaj wpisz opis obrazka

Edit
Oficjalna strona tego pakietu znajduje się tutaj (z wieloma przykładami!): https://github.com/timelyportfolio/sunburstR

Hat Tip dla @ timelyportfolio, który stworzył ten imponujący kawałek kodu!

 24
Author: vonjd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-01 15:38:34

Możesz utworzyć coś wzdłuż linii wykresu sunburst używając geom_tile z pakietu ggplot2. Najpierw stwórzmy losowe DANE:

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

A następnie utworzyć wykres rastrowy. W tym przypadku oś x na wykresie jest sprzężona ze zmienną x W dat, oś y ze zmienną y, a wypełnienie pikseli ze zmienną z. Daje to następujący wykres:

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

Tutaj wpisz opis obrazka

Pakiet ggplot2 obsługuje wszystkie rodzaje przekształceń współrzędnych, jedna z nich zajmuje jedną oś i rzutuje ją na okrąg, tj. współrzędne biegunowe:

p + coord_polar()

Tutaj wpisz opis obrazka

To z grubsza robi to, czego potrzebujesz, teraz możesz dostosować dat, aby uzyskać pożądany rezultat.

 11
Author: Paul Hiemstra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-29 07:48:44

Istnieje pakiet o nazwie ggsunburst. Niestety nie jest w CRAN, ale można zainstalować zgodnie z instrukcją na stronie: http://genome.crg.es / ~didac/ggsunburst/ggsunburst.html .

Tutaj wpisz opis obrazka

Mam nadzieję, że pomoże to osobom, które nadal szukają dobrego pakietu.

Pozdrawiam,

 5
Author: jbkunst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-22 15:55:16

Jest tylko kilka bibliotek, które znam, które robią to natywnie:

Żadne z nich nie jest w Pythonie ani R, ale uzyskanie skryptu Pythona / R do zapisu prostego pliku JSON, który może być załadowany przez jedną z bibliotek javascript, powinno być całkiem możliwe.

 3
Author: jozzas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-17 04:42:48

Oto ggplot2 sunburst z dwiema warstwami.

Podstawową ideą jest po prostu zrobić inny pasek dla każdej warstwy i uczynić pręty szerszymi dla warstw zewnętrznych. Pomieszałem też z osią x, aby upewnić się, że nie ma dziury w środku wewnętrznego wykresu kołowego. W ten sposób można kontrolować wygląd sunburst poprzez zmianę szerokości i wartości osi 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')

Tutaj wpisz opis obrazka

Jedyną wadą w porównaniu z oprogramowaniem specyficznym dla sunburst jest to, że zakłada, że chcesz warstwy zewnętrzne powinny być zbiorczo wyczerpujące (tzn. bez przerw). "Częściowo wyczerpujące" warstwy zewnętrzne (jak w niektórych innych przykładach) są z pewnością możliwe, ale bardziej skomplikowane.

Dla kompletności, tutaj jest oczyszczony z ładniejszym formatowaniem i etykietami:

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

Tutaj wpisz opis obrazka

 3
Author: dmp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-21 22:30:55

Ponieważ jbkunst wspomniał o ggsunburst, tutaj zamieszczam przykład odtwarzania sunburst przez sirex.

To nie jest dokładnie to samo, ponieważ w ggsunburst kąt węzła jest równy sumie kątów jego węzłów potomnych.

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

Tutaj wpisz opis obrazka

 1
Author: didac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-12 23:52:45