‘visNetwork’ jest pakietem języka R który służy do wizualizacji sieci, używając biblioteki ‘vis.js’ języka javascript.
[komentarz] Pojawiło się dużo nazw pakietów, żeby się nie pogubić jedno zdanie o każdym: ‘visNetwork’ = Nasz pakiet do wizualizacji i robienia wykresów ‘vis.js’ = to jest biblioteka javascript która odpowiada za wyświetlanie tych wszystkich rzeczy w przeglądarce, plus posiada w sobie kawałki bibliotek ‘DataSet’, ‘Timeline’, ‘Network’, ‘Graph2d’, ‘Graph3d’. ‘htmlwidgets’ = odpowiada za używanie javascript w konsoli R, prostymi słowami to jest to co pokazuje nam obrazki wykresów (i inne) w prawym dolnym rogu R ‘Shiny’ = Pakiet R który odpowiada za budowanie interaktywnych web-apps prosto w R. ‘R Markdown documents’ = file format for making dynamic documents with R ‘RStudio viewer’ = to jest po prostu nasz graficzny interfejs R (jak klikamy w dataset i mamy wizualnie tabelkę itd.)
[komentarz] W kodzie pojawia się mało znany operator >%> aka pipe-forward. Używa się go aby nie pisać funkcji w funkcji: plot_it(summarize_it(transform_it(clean_it(read_it(x))))) z użyciem >%> to spaghetti na górze wygląda: x %>% read_it %>% clean_it %>% transform_it %>% summarize_it %>% plot_it
Aby skorzystać z dodatkowych pakietów w R należy wykonać dwa kroki: 1.Zainstalować nowy pakiet.. Ten krok wystarczy wykonać raz, skopiuje on niezbędne pliki do katalogu z pakietami. 2.Włączyć zainstalowany pakiet w działającej sesji R. Ten krok należy wykonać po każdym uruchomieniu środowiska R. Spowoduje on, że w aktualnej sesji będzie można korzystać z funkcji i zbiorów danych dostępnych w pakiecie.
install.packages("visNetwork")
library(visNetwork)
Możemy dostosować węzły wieloma opcjami na wiele różnych sposobów.
Węzły ‘nodes’ muszą być ramką danych ‘data.frame’, z co najmniej jedną kolumną ‘id’. Węzeł konfigurujemy poprzez dodanie zmiennych do ‘data.frame’. Żeby zobaczyć wszystkie opcje można wywołać ‘?visNodes’.
Przykład zawierający najczęściej używane opcje:
nodes <- data.frame(id = 1:10,
# dodanie etykiety na węzeł
label = paste("Węzeł", 1:10),
# dodanie grup do węzełóW
group = c("GrA", "GrB"),
# przypisanie wielkości skalujących
value = 1:10,
# ustalenie wyglądu każdego węzła
shape = c("square", "triangle", "box", "circle", "dot", "star",
"ellipse", "database", "text", "diamond"),
# co ma sie wyświetlać gdy najedziemy na węzeł myszką
title = paste0("To jest węzeł numer ", 1:10),
# kolor
color = c("darkred", "grey", "orange", "blue", "purple"),
# cień
shadow = c(FALSE, TRUE, FALSE, TRUE, TRUE))
# stworzenie połączeń pomiędzy węzłami
edges <- data.frame(from = c(1,2,3,4,5,6), to = c(9,8,7,1,1,5))
# wizualizacja
visNetwork(nodes, edges, height = "500px", width = "100%")
[Komentarz] Tutaj mamy przykład numer dwa, który mogę napisać od ręki tylko muszę mieć wenę jaki kształt to ma być. Coś takiego że damy kilogram węzłów i one w jakiś śmieszny kształt sie ułożą na przykład glona.
Jeżeli chcemy ustawić jakąś konfiguracje dla wszystkich węzłów, możemy to zrobić w prosty sposób używając wbudowanych funkcji ‘visNodes’ :
nodes <- data.frame(id = 1:6)
edges <- data.frame(from = c(1,1,1,1,1), to = c(2,3,4,5,6))
visNetwork(nodes, edges, width = "100%") %>%
visNodes(shape = "circle",
color = list(background = "lightblue",
border = "darkblue",
highlight = "yellow"),
shadow = list(enabled = TRUE, size = 10)) %>%
visLayout(randomSeed = 420)
Możemy łączyć ze sobą konfiguracje indywidualną i globalną:
nodes <- data.frame(id = 1:6,
shape = "square",
label = LETTERS[1:6])
edges <- data.frame(from = c(1,1,1,1,1), to = c(2,3,4,5,6))
visNetwork(nodes, edges, width = "100%") %>%
visNodes(shape = "circle",
color = list(background = "lightblue",
border = "darkblue",
highlight = "yellow"),
shadow = list(enabled = TRUE, size = 10)) %>%
visLayout(randomSeed = 420)
Gdy opcje są dostępne przy użyciu listy, możemy użyć ich w ramce danych z określoną notacją:
nodes <- data.frame(id = 1:4,
color.background = c("red", "blue", "green", "pink"),
color.highlight.background = c("yellow", NA, "cyan", "magenta"),
shadow.size = c(5, 10, 15, 20))
edges <- data.frame(from = c(1,2), to = c(2,4),
label = LETTERS[1:4],
font.color =c ("red", "blue", "green", "pink"),
font.size = c(10,20,30,40))
visNetwork(nodes, edges)
Możemy dostosować krawędzie wieloma opcjami na wiele różnych sposobów, w taki sam sposób jak węzły.
Krawędzie ‘edges’ muszą być ramką danych ‘data.frame’, z co najmniej jedną kolumną ‘from’ i ‘to’’. Węzeł konfigurujemy poprzez dodanie zmiennych do ‘data.frame’. Żeby zobaczyć wszystkie opcje można wywołać ‘?visNodes’.
Najczęściej używane są przedstawione w poniższym przykładzie:
Jeżeli chcemy ustawić jakąś konfiguracje dla wszystkich krawędzi, możemy to zrobić w prosty sposób używając wbudowanych funkcji ‘visEdges’ :
nodes <- data.frame(id = 1:9)
edges <- data.frame(from = c(2,4,3,5,7,6,9,2,8), to = c(1,2,4,3,6,5,7,8,9))
visNetwork(nodes, edges, width = "100%") %>%
visEdges(shadow = TRUE,
arrows = list(to = list(enabled = TRUE, scaleFactor = 2)),
color = list(color = "green", highlight = "pink")) %>%
visLayout(randomSeed = 12)
nodes <- data.frame(id = 1:4, label = 1:4)
edges <- data.frame(from = c(2,4,3,2),
to = c(1,2,4,3),
dashes = c(TRUE, FALSE))
visNetwork(nodes, edges, width = "100%") %>%
visEdges(shadow = TRUE,
arrows =list(to = list(enabled = TRUE, scaleFactor = 2)),
color = list(color = "lightblue", highlight = "red")) %>%
visLayout(randomSeed = 12)
Gdy opcje są dostępne przy użyciu listy, możemy użyć ich w ramce danych z określoną notacją:
visNetwork(nodes, edges, height = "500px", width = "100%")
nodes <- data.frame(id = 1:3,
color.background = c("red", "blue", "green"),
color.highlight.background = c("red", NA, "red"),
shadow.size = c(5, 15, 25))
edges <- data.frame(from = c(1,2), to = c(1,3),
label = LETTERS[1:2],
font.color =c ("pink", "black"),
font.size = c(10,20))
visNetwork(nodes, edges)
Możesz oddziaływać na grupę do węzła używając kolumny ‘group’ w węźle data.frame, i dodać konfiguracje dla grupy używając ‘visGroups’.
nodes <- data.frame(id = 1:5, group = c(rep("A", 2), rep("B", 3)))
edges <- data.frame(from = c(1,2,3,4,5), to = c(2,3,1,1,1))
visNetwork(nodes, edges, width = "100%") %>%
# grupa A kwadraty koloru cyan
visGroups(groupname = "A", color = "cyan", shape = "square") %>%
# grupa B trojkaty koloru rozowego
visGroups(groupname = "B", color = "pink", shape = "triangle")
Możesz dodać tytuł (‘main’), podtytuł (‘subtitle’) oraz stopkę (‘footer’) do swojej sieci:
nodes <- data.frame(id = 1:3)
edges <- data.frame(from = c(1,2), to = c(2,3))
visNetwork(nodes, edges,
main = "Prosty przyklad",
submain = list(text = "Twój podtytul",
style = "font-family:Comic Sans MS;color:#ff0000;font-size:15px;text-align:center;"),
footer = "Twoja stopka",
width = "100%")
Aby użyć obrazów w węzłach, najpierw musisz ustawić shape w image lub circularImage. Następnie ustaw ścieżkę względną lub bezwzględną na wartości image W przypadku błędnej ścieżki dostępna jest opcja: brokenImage Możesz używać obramowań z shapeProperties i useBorderWithImage
path_to_images <- "https://raw.githubusercontent.com/datastorm-open/datastorm-open.github.io/master/visNetwork/data/img/indonesia/"
nodes <- data.frame(id = 1:4,
shape = c("image", "circularImage"),
image = paste0(path_to_images, 1:4, ".png"),
label = "I'm an image")
edges <- data.frame(from = c(1,4,3,2), to = c(1,2,4,2))
visNetwork(nodes, edges, width = "100%") %>%
visNodes(shapeProperties = list(useBorderWithImage = TRUE)) %>%
visLayout(randomSeed = 2)
visNetwork obsługuje ikony fontAwesome. Font-awesome nie jest częścią domyślnych zależności, ale w razie potrzeby możesz użyć addFontAwesome().
Aby używać ikon w węzłach, musisz najpierw ustawić kształt na ikonę. Opcje ikon muszą być listą, więc musisz użyć visNodes lub visGroups lub przekazać bezpośrednio w nodes data.frame (patrz przykład Ionicons poniżej) Wybierz ikonę według kodu, ustaw rozmiar i kolor
nodes <- data.frame(id = 1:3, group = c("B", "A", "B"))
edges <- data.frame(from = c(1,2), to = c(2,3))
visNetwork(nodes, edges, width = "100%") %>%
visGroups(groupname = "A", shape = "icon",
icon = list(code = "f0c0", size = 75)) %>%
visGroups(groupname = "B", shape = "icon",
icon = list(code = "f007", color = "red")) %>%
addFontAwesome()
Obsługa ikon Ionicons. W przypadku wystepowania zależności możesz w razie potrzeby użyć addIonicons(). Proces definiowania jest taki sam jak w przypadku ikon fontAwesome, z wyjątkiem tego, że musisz ustawić set = ‘Ionicons’.
nodes <- data.frame(id = 1:3, shape = "icon", icon.face = 'Ionicons',
icon.code = c("f101", "f100", "f101"))
edges <- data.frame(from = c(1,2), to = c(2,3))
visNetwork(nodes, edges) %>%
addIonicons()
Niektóre opcje niestandardowe są dostępne za pomocą visOptions().
nb <- 10
nodes <- data.frame(id = 1:nb, label = paste("Label", 1:nb),
group = sample(LETTERS[1:3], nb, replace = TRUE), value = 1:nb,
title = paste0("<p>", 1:nb,"<br>Tooltip !</p>"), stringsAsFactors = FALSE)
edges <- data.frame(from = c(8,2,7,6,1,8,9,4,6,2),
to = c(3,7,2,7,9,1,5,3,2,9),
value = rnorm(nb, 10), label = paste("Edge", 1:nb),
title = paste0("<p>", 1:nb,"<br>Edge Tooltip !</p>"))
Możesz podświetlić najbliższe węzły i krawędzie, klikając węzeł za pomocą funkcji HighlightNearest. Po prostu kliknij wszędzie z wyjątkiem węzłów, aby zresetować sieć:
visNetwork(nodes, edges, height = "500px", width = "100%") %>%
visOptions(highlightNearest = TRUE) %>%
visLayout(randomSeed = 123)
Możliwe jest teraz kontrolowanie stopnia głębokości, a włączenie tej opcji umożliwia również najeżdżanie na węzły (najechanie). Po najechaniu kursorem możesz nadal używać kliknięcia, aby ustawić widok :
visNetwork(nodes, edges, height = "500px", width = "100%") %>%
visOptions(highlightNearest = list(enabled = T, degree = 2, hover = T)) %>%
visLayout(randomSeed = 123)
Ta funkcja jest dostępna również z obrazami i ikonami:
visNetwork(nodes, edges, height = "500px", width = "100%") %>%
visGroups(groupname = "A", shape = "icon",
icon = list(code = "f0c0", size = 75)) %>%
visGroups(groupname = "B", shape = "icon",
icon = list(code = "f007", color = "red")) %>%
visGroups(groupname = "C", shape = "icon",
icon = list(code = "f1b9", color = "black")) %>%
visOptions(highlightNearest = list(enabled =TRUE, degree = 2, hover = T)) %>%
addFontAwesome() %>%
visLayout(randomSeed = 123)
Możesz również wybrać węzeł według id/etykiety z listą za pomocą nodesIdSelection:
visNetwork(nodes, edges, height = "500px", width = "100%") %>%
visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE) %>%
visLayout(randomSeed = 123)
Wybierz podzbiór węzłów według wartości kolumny za pomocą selectedBy. Węzły mogą mieć wiele grup przy użyciu wartości oddzielonych przecinkami:
w “autoryzowanej” kolumnie
visNetwork(nodes, edges, height = "500px", width = "100%") %>%
visOptions(selectedBy = "group") %>%
visLayout(randomSeed = 123)
w nowej kolumnie z wieloma grupami
nodes$sample <- paste(sample(LETTERS[1:3], nrow(nodes), replace = TRUE),
sample(LETTERS[1:3], nrow(nodes), replace = TRUE),
sep = ",")
nodes$label <- nodes$sample
visNetwork(nodes, edges, height = "500px", width = "100%") %>%
visOptions(selectedBy = list(variable = "sample", multiple = T)) %>%
visLayout(randomSeed = 123)
Dostępnych jest wiele funkcji umożliwiających dostosowanie selectedBy & nodesIdSelection, na przykład:
wartości : kontroluj dostępne wartości na liście wybrane: zainicjuj wybór styl: dostosuj css listy To jest przykład bazujacy na nodesIdSelection :
visNetwork(nodes, edges, height = "500px", width = "100%") %>%
visOptions(highlightNearest = TRUE,
nodesIdSelection = list(enabled = TRUE,
selected = "8",
values = c(5:10),
style = 'width: 200px; height: 26px;
background: #f8f8f8;
color: darkblue;
border:none;
outline:none;')) %>%
visLayout(randomSeed = 123)
nodes <- data.frame(id = 1:15, label = paste("Label", 1:15),
group = sample(LETTERS[1:3], 15, replace = TRUE))
edges <- data.frame(from = trunc(runif(15)*(15-1))+1,
to = trunc(runif(15)*(15-1))+1)
# keeping all parent node attributes
visNetwork(nodes, edges) %>% visEdges(arrows = "to") %>%
visOptions(collapse = TRUE)
Korzystając z manipulacji, możesz edytować swoją sieć:
Dodaj/usuń węzły/krawędzie Zmień linki
visNetwork(nodes, edges, height = "500px", width = "100%") %>%
visOptions(manipulation = TRUE) %>%
visLayout(randomSeed = 123)
nodes <- jsonlite::fromJSON("https://raw.githubusercontent.com/datastorm-open/datastorm-open.github.io/master/visNetwork/data/nodes_miserables.json")
edges <- jsonlite::fromJSON("https://raw.githubusercontent.com/datastorm-open/datastorm-open.github.io/master/visNetwork/data/edges_miserables.json")
visNetwork(nodes, edges, height = "700px", width = "100%") %>%
visOptions(selectedBy = "group",
highlightNearest = TRUE,
nodesIdSelection = TRUE) %>%
visPhysics(stabilization = FALSE)
Układ można konfigurować za pomocą funkcji visLayout() i visHierarchicalLayout().
Węzły są początkowo rozmieszczone losowo. Oznacza to, że ustalony wynik jest za każdym razem inny. Jeśli podasz losowe ziarno ręcznie (randomSeed), układ będzie za każdym razem taki sam.
Możesz używać i kontrolować układ hierarchiczny z niektórymi opcjami:
levelSeparation- odległość między różnymi poziomami. direction- kierunek układu hierarchicznego. sortMethod- algorytm używany do określania poziomów węzłów na podstawie danych
nodes <- data.frame(id = 1:7)
edges <- data.frame(from = c(1,2,2,2,3,3),
to = c(2,3,4,5,6,7))
visNetwork(nodes, edges, width = "100%") %>%
visEdges(arrows = "from") %>%
visHierarchicalLayout()
visNetwork(nodes, edges, width = "100%") %>%
visEdges(arrows = "from") %>%
visHierarchicalLayout(direction = "LR", levelSeparation = 500)
Możliwe jest również zdefiniowanie poziomu każdego węzła:
nodes <- data.frame(id = 1:4, level = c(2, 1, 1, 1))
edges <- data.frame(from = c(1, 1, 1),
to = c(2,3,4))
Z poziomem wezla:
visNetwork(nodes, edges, width = "100%") %>%
visEdges(arrows = "from") %>%
visHierarchicalLayout()
Brak poziomu wezla:
nodes$level <- NULL
visNetwork(nodes, edges, width = "100%") %>%
visEdges(arrows = "from") %>%
visHierarchicalLayout()
Od visNetwork_0.2.1 możliwe jest powiązanie funkcji pakietu igraph z funkcjami visNetwork. Użyj układu igraph do obliczenia współrzędnych w celu szybkiego renderowania za pomocą visIgraphLayout() Przekształć sieć igraph w sieć visNetwork za pomocą visIgraph() lub toVisNetworkData()
Dzięki visIgraphLayout() możesz wykorzystać wszystkie dostępne układy w igraph i obliczyć współrzędne przed wysłaniem do vis.js :
nnodes <- 100
nnedges <- 200
nodes <- data.frame(id = 1:nnodes)
edges <- data.frame(from = sample(1:nnodes, nnedges, replace = T),
to = sample(1:nnodes, nnedges, replace = T))
visNetwork(nodes, edges, height = "500px") %>%
visIgraphLayout() %>%
visNodes(size = 10)
visNetwork(nodes, edges, height = "500px") %>%
visIgraphLayout(layout = "layout_in_circle") %>%
visNodes(size = 10) %>%
visOptions(highlightNearest = list(enabled = T, hover = T),
nodesIdSelection = T)
visIgraph bezpośrednio przekształca sieć igraph w visNetwork. Możesz również użyć toVisNetworkData, aby po prostu uzyskać dane w formacie visNetwork:
library("igraph", quietly = TRUE, warn.conflicts = FALSE, verbose = FALSE)
## Warning: package 'igraph' was built under R version 4.0.5
igraph_network <- graph.famous("Walther")
plot(igraph_network)
dane i wykres:
data <- toVisNetworkData(igraph_network)
visNetwork(nodes = data$nodes, edges = data$edges, height = "500px")
lub tylko wykres:
visIgraph(igraph_network)
Przy domyślnych/niektórych opcjach renderowanie sieci może zająć dużo czasu. Oto kilka sposobów na poprawę wydajności:
Domyślnie, jeśli nie przekazujemy żadnych informacji o współrzędnych, vis.js oblicza współrzędne dynamicznie i czeka na stabilizację przed renderowaniem. Możesz wyłączyć lub kontrolować stabilizację za pomocą visPhysics :
visNetwork(nodes, edges) %>%
visPhysics(stabilization = FALSE)
Kolejną wskazówką jest wyłączenie gładkiej krzywej dla krawędzi. To prowadzi do lepszej wydajnosci:
visNetwork(nodes, edges) %>%
visEdges(smooth = FALSE)
Możliwe jest powiązanie funkcji pakietu igraph z funkcjami visNetwork. Najlepszym sposobem na wydłużenie czasu kreślenia grafu jest użycie układu igraph do obliczenia współrzędnych wcześniej za pomocą visIgraphLayout():
visNetwork(nodes, edges) %>%
visIgraphLayout()
Od wersji visNetwork_2.0.0 możesz wizualizować drzewa klasyfikacji i regresji z danych wyjściowych pakietu rpart, używając po prostu visTree :
library(rpart)
library(htmlwidgets)
## Warning: package 'htmlwidgets' was built under R version 4.0.5
library(sparkline)
## Warning: package 'sparkline' was built under R version 4.0.5
res <- rpart(Species~., data=iris)
visTree(res, main = "Iris classification Tree", width = "100%")
res <- rpart(Petal.Length~., data=iris)
visTree(res, edgesFontSize = 14, nodesFontSize = 16, width = "100%")
data("solder")
res <- rpart(Opening~., data = solder, control = rpart.control(cp = 0.00005))
visTree(res, height = "800px", nodesPopSize = TRUE, minNodeSize = 10,
maxNodeSize = 30, width = "100%")
Spójrz na visTreeEditor, aby edytować i wrócić do sieci, oraz na visTreeModuleServer, aby użyć niestandardowego modułu drzewa w R.
Korzystaj z sieci w Shiny dzięki visNetworkOutput i renderVisNetwork
require(shiny)
## Loading required package: shiny
## Warning: package 'shiny' was built under R version 4.0.5
require(visNetwork)
server <- function(input, output) {
output$mynetworkid <- renderVisNetwork({
# minimal example
nodes <- data.frame(id = 1:3)
edges <- data.frame(from = c(1,2), to = c(1,3))
visNetwork(nodes, edges)
})
}
ui <- fluidPage(
visNetworkOutput("mynetworkid")
)
shinyApp(ui = ui, server = server)
dane wejściowe są tworzone po zainicjowaniu sieci: input$mynetworkid_initialized z nodesIdSelection możesz uzyskać dostęp do nowych danych wejściowych z bieżącą wartością wyboru:
Aby nie przerysowywać całej sieci, możesz użyć funkcji visNetworkProxy w shiny, a następnie zmienić konfigurację swojej sieci bez jej przerysowywania.
Możesz korzystać z prawie wszystkich funkcji dostępnych w visNetworkProxy, a nawet z niektórych funkcji specjalnych.
klasyczne funkcje: visNodes, visEdges, visGroups, visOptions (>=0.2.2), visPhysics, visInteraction, visLayout & visHierarchicalLayout
funkcje specjalne (metody vis.js):
visFocus : skoncentruj się na jednym węźle docelowym visFit : dopasuj widok do jednego lub kilku węzłów visUpdateNodes / visUpdateEdges : aktualizuj / dodaj dane visRemoveNodes / visRemoveEdges : usuń dane visSelectNodes / visSelectEdges / visSetSelection: wybór a także visRedraw, visStabilize,visSetData,visGetPositions,visMoveNode,visUnselectAll
require(shiny)
require(visNetwork)
server <- function(input, output) {
output$network_proxy_nodes <- renderVisNetwork({
nodes <- data.frame(id = 1:3)
edges <- data.frame(from = c(1,2), to = c(1,3))
visNetwork(nodes, edges) %>% visNodes(color = "blue")
})
observe({
visNetworkProxy("network_proxy_nodes") %>%
visFocus(id = input$Focus, scale = 4)
})
observe({
visNetworkProxy("network_proxy_nodes") %>%
visNodes(color = input$color)
})
}
ui <- fluidPage(
fluidRow(
column(
width = 4,
selectInput("color", "Color :",
c("blue", "red", "green")),
selectInput("Focus", "Focus on node :",
c(1:3))
),
column(
width = 8,
visNetworkOutput("network_proxy_nodes", height = "400px")
)
)
)
shinyApp(ui = ui, server = server)