簡體   English   中英

在for循環中優化add_trace()?

[英]Optimizing add_trace() in a for loop?

我在for循環中使用add_trace()函數在plotly的scatter3d模式下為3d網絡圖創建線。 每個add_trace在網絡中的兩個節點之間繪制一條單獨的線。 該方法正在運行,但是在循環很多的情況下,各個循環的速度似乎正在迅速降低。

示例數據可以在這里下載: https : //gist.github.com/pravj/9168fe52823c1702a07b

library(igraph)
library(plotly)

G <- read.graph("karate.gml", format = c("gml"))
L <- layout.circle(G)

vs <- V(G)
es <- as.data.frame(get.edgelist(G))

Nv <- length(vs)
Ne <- length(es[1]$V1)

Xn <- L[,1]
Yn <- L[,2]

network <- plot_ly(type = "scatter3d", x = Xn, y = Yn, z = rep(0, Ne), mode = "markers", text = vs$label, hoverinfo = "text", showlegend = F)

for(i in 1:Ne) {
  v0 <- es[i,]$V1
  v1 <- es[i,]$V2

  x0 <-  Xn[v0]
  y0 <-  Yn[v0]
  x1 <-  Xn[v1]
  y1 <-  Yn[v1]

  df <-  data.frame(x = c(x0, x1), y = c(y0, y1), z = c(0, 0))
  network <- add_trace(network, data = df, x = x, y = y, z = z, type = "scatter3d", mode = "lines", showlegend = F, 
                       marker = list(color = '#030303'), line = list(width = 0.5))
}

這個例子相當快,但是當我包含幾百條或更多條邊時,各個循環的執行速度便開始顯着降低。 我嘗試了不同的優化方法(矢量化等),但似乎無法解決add_trace函數本身的緩慢問題。

有什么建議么?

在plotly中添加許多線段的最有效方法不是將每個線段都作為單獨的跡線,而是僅使用包含所有線段的單個跡線。 您可以通過構造一個數據幀來實現,該數據幀具有要連接的每個節點的x,y坐標,並在每個線段之間散布着NA。 然后使用connectgaps=FALSE將跡線分成每個NA的單獨段。 您可以在此答案中看到適用於意大利面條圖的此方法的另一個示例。

es$breaks <- NA
lines <- data.frame(node=as.vector(t(es)), x=NA, y=NA, z=0)
lines[which(!is.na(lines$node)),]$x <- Xn[lines[which(!is.na(lines$node)),]$node]
lines[which(!is.na(lines$node)),]$y <- Yn[lines[which(!is.na(lines$node)),]$node]

network <- plot_ly(type = "scatter3d", x = Xn, y = Yn, z = rep(0, Ne), 
                   mode = "markers", text = vs$label, hoverinfo = "text", 
                   showlegend = F) %>% 
  add_trace(data=lines, x=x, y=y, z=z, showlegend = FALSE,
                      type = 'scatter3d', mode = 'lines+markers',
                      marker = list(color = '#030303'), line = list(width = 0.5),
                      connectgaps=FALSE)

在此處輸入圖片說明

該問題的可重復數據

為了方便起見,以下是此問題的數據。 OP需要從github下載.gml文件,並安裝library(igraph)將數據處理到其中。

es <- structure(list(
  V1 = c(1, 1, 2, 1, 2, 3, 1, 1, 1, 5, 6, 1, 2, 3, 4, 1, 3, 3, 1, 5, 6, 1, 1, 4, 1, 2, 3, 4, 6, 7, 1, 2, 1, 2, 
    1, 2, 24, 25, 3, 24, 25, 3, 24, 27, 2, 9, 1, 25, 26, 29, 3, 9, 15, 16, 19, 21, 23, 24, 30, 31, 32, 9, 10, 14, 15, 16, 19, 20, 
    21, 23, 24, 27, 28, 29, 30, 31, 32, 33), 
  V2 = c(2, 3, 3, 4, 4, 4, 5, 6, 7, 7, 7, 8, 8, 8, 8, 9, 9, 10, 11, 11, 11, 12, 13, 13, 
    14, 14, 14, 14, 17, 17, 18, 18, 20, 20, 22, 22, 26, 26, 28, 28, 28, 29, 30, 30, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 
    33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34)), 
  .Names = c("V1", "V2"), row.names = c(NA, -78L), class = "data.frame")

theta <- seq(0,2,length.out=35)[1:34]
Xn <- cospi(theta)
Yn <- sinpi(theta)

Nv <- NROW(Xn)
Ne <- NROW(es)
vs <- data.frame(label = as.character(1:Nv))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM