簡體   English   中英

來自序列的R定向網絡

[英]R directed network from sequence

(使用:R 3.1.0)

嗨-我覺得這應該比我發現的要簡單。 我有一組序列,我想將它們可視化為有向網絡。 單純的圖形可能不合適,因為每個序列可以具有多個節點實例,並且重復順序在序列中很重要。 因此,例如,我可能有:

Seq    Count
AB     8000
AC     5500
CB     4900
CBA    4300
ACD    4000
ACACA  3740
CA     2800
...    ...

序列的結尾位置很有趣,因此對於每個最終節點,我都希望顯示其路徑及其權重。 因此,在我上面的示例中(非常小):

  • 端點B: A-> B的權重為8000, C-> B的權重為4900。

     8000 A-+ |-->B 4900 C-+ 
  • 端點A: C-> B-> A的重量為4300, A-> C-> A-> C-> A的重量為3740, C-> A的重量為2800

      4300 C--->B-+ | 4740 A-->C-->A-->C-+--->A | 2800 C-+ 

重要的是要注意,路由CA不是ACACA的一部分,而是單獨的路由。

原始數據實際上是按時間順序按序列號分組的事件列表,因此從該點開始可能更容易(而不是上面的聚合視圖)。 像這樣:

seqNo. Node  Time
1      A     0.0
1      B     2.1
2      A     0.0
2      C     3.2
3      C     0.0
3      B     8.1
4      C     0.0
4      B     1.2
4      A     2.3
...    ...   ...

我想知道哪種軟件包(如果有的話)最適合用於這樣的序列,以及如何將數據減少到定向網絡視圖。 iGraph軟件包看起來可能會有所幫助,但我認為可能缺少一些概念,尤其是在這種情況下,鄰接矩陣並不是真正有效的(由於圖中每對節點都有多個鄰接關系)。

更新-這是我正在尋找的輸出類型的想法:

我要尋找的例子

歡呼,感謝您的幫助,

安迪。

您似乎在說,只有起點和終點才是節點,因此可以將這些節點用作頂點,並將中間節點顯示為邊緣標簽,如以下代碼和圖所示。 假設df包含您的匯總數據。

library(igraph)
last_char <- nchar(as.character(df$Seq))
df_g <- cbind(v1=substr(df$Seq, 1,1),
              v2=substr(df$Seq, last_char, last_char), df)
g <- graph.data.frame(df_g)
plot(g, edge.label=paste(E(g)$Seq, "\n", E(g)$Count))

該圖的可視化表示可以改善,但這顯示了匯總數據可以產生定向網絡視圖的方式。 可以想象一些替代方法來表示起始節點和結束節點之間的內部節點,但是這些方法似乎會導致更為復雜的繪圖。

更新2

您的評論使事情變得更加清晰。 獲取圖表的大部分工作是從序列數據生成圖形的邊和頂點。 定義后,您可以格式化並發送到繪圖包進行顯示。 下面的代碼構造的數據幀df_g含有邊緣連接位置和結束位置,使用df_g以產生數據幀df_v包含頂點數據,然后通過既igraph用於繪圖。 您可以通過檢查df_gdf_vdf_g代碼的df_v

  library(igraph)
  last_char <- nchar(df$Seq)
  df <- df[order(substr(df$Seq, last_char, last_char), df$Seq),]
  edges <- as.character(df$Seq)
  df_g <- data.frame(v1=NA_character_, v2=NA_character_, Seq=NA_character_, 
                     Count=NA_character_, label=NA_character_, arrow.mode = NA_character_, end = NA_character_, 
                     x1 = NA_integer_, x2 = NA_integer_, y1=NA_integer_, y2=NA_integer_,  type=NA_character_,
                     stringsAsFactors=FALSE)
  for( i in 1:nrow(df)){
 #  Make sequence edges
      edge <- edges[i]
      num_vert <- nchar(edge)
      j <- 1:(num_vert-1)
      df_g_j <- data.frame( v1=paste(edge, j,sep="_"), v2=paste(edge, j+1,sep="_"), 
                         Seq=edge, Count=df$Count[i], label=sapply(j, function(x) substr(edge, x, x)), 
                         arrow.mode = ">", end=substr(edge,num_vert,num_vert),
                         x1=j-num_vert, x2=j+1-num_vert,  y1=i, y2=i, type="seq", stringsAsFactors=FALSE) 
      df_g_j[num_vert-1, "arrow.mode"] <- "-"       # make connector vertex   
      df_g_con <- transform(df_g_j[num_vert-1,], v1=v2, v2=paste(end, "connector", sep="_"), x1=0, label=NA, type="connector")
      df_g <- rbind(df_g, df_g_j, df_g_con)    
    }
    df_g <- df_g[-1,]
    df_g[df_g$type=="connector",] <- within(df_g[df_g$type=="connector",], y2 <- tapply(y2, v2, mean)[v2])
    cn_vert <- aggregate(v2 ~ end, data=df_g[df_g$type=="connector", ], length)
    colnames(cn_vert) <- c("end","num")
    for( end in cn_vert$end){
      cn_vert_row <- which(df_g$end == end & df_g$type == "connector")[1]
      if( cn_vert$num[cn_vert$end==end] > 1 ) {
        df_g <- rbind(df_g,with(df_g[cn_vert_row,], 
                                data.frame(v1=v2, v2=end, Seq=NA_character_, Count=NA_character_, label=NA,
                                           arrow.mode = ">", end=end, x1=x2, x2= 1, y1 = y2, y2=y2, type = "common_end", 
                                          stringsAsFactors=FALSE)) ) }
      else df_g[cn_vert_row,] <- transform(df_g[cn_vert_row,], v2=end, label=NA, arrow.mode=">", x2=1,type="common_end")
  }
#  make vertices
  df_v <- with(df_g, data.frame(v=v1, label = label, x=x1, y=y1, color = "black", size = 15, stringsAsFactors=FALSE))
  df_v <- rbind(df_v, with(df_g[df_g$type == "common_end",], 
                           data.frame(v=end, label = v2, x=x2, y=y2, color="black", size=15, stringsAsFactors=FALSE)))
  df_v[is.na(df_v$label),] <- transform(df_v[is.na(df_v$label),], color = NA, size = 0)
#
#  make graph from edges and vertices
  g <- graph.data.frame(df_g, vertices=df_v)
  E(g)$label <- NA                       # assign Counts as labels to sequence start vertices
  e_start <- grep("_1",get.edgelist(g)[,1])
  E(g)[e_start]$label <- E(g)[e_start]$Count
# adjust and scale edge label positions
  h_jst <- 0            # values between 0 and .2
  edge_label_x  <- 1 - 2*(1.5 + h_jst - E(g)$x1)/diff(range(V(g)$x))
  num_color <-12                           # assign colors to Count labels; num_color is number of colors in pallette
  counts <- as.integer(E(g)$Count)
  edge_label_color <- rainbow(num_color, start=0, end=.75)[num_color- 
                                         floor((num_color-1)*(counts-min(counts,na.rm=TRUE))/diff(range(counts,na.rm=TRUE)))]
  plot(g, vertex.label.color="white", vertex.frame.color=V(g)$color, 
       edge.color="blue", edge.arrow.size=.6, edge.label.x= edge_label_x, 
       edge.label.color=edge_label_color, edge.label.font=2, edge.label.cex=1.1)

對於您的示例數據,這給出了下圖所示。 擴大繪圖時,“計數”標簽與頂點之間的距離更大,但是您可以通過在代碼內使用變量h_jst進一步進行調整。

在此處輸入圖片說明

我發現了一個可以(雖然很冗長)以一種可以接受的方式很好解決了這個問題的程序包,盡管從格式化的角度來看,這並不是我所尋找的。

使用DigrammeR包(可通過grViz函數實現graphViz ),我可以設計一個看起來像問題中所需輸出的網絡。 該語言比較冗長,但是一旦發現合適的網絡路徑, grViz容易構造可grViz算法提供給grViz的代碼。

代碼是:

library(DiagrammeR)
library(V8)
library(XML)

gph<-grViz("
  digraph {
    outputorder=edgesfirst;
    rankdir='LR';
    node [shape = circle, style='filled', fillcolor = black, fontname=Arial, fontcolor=white];

    A1 -> C1 -> D1              [color='cornflowerblue', penwidth=3];
    A2 -> C2                    [color='cornflowerblue', penwidth=3];
    C3 -> B1                    [color='cornflowerblue', penwidth=3];
    A3 -> B1                    [color='cornflowerblue', penwidth=3];
    C4 -> B2 -> A4              [color='cornflowerblue', penwidth=3];
    C5 -> A4                    [color='cornflowerblue', penwidth=3];
    A5 -> C6 -> A6 -> C7 -> A4  [color='cornflowerblue', penwidth=3];

    w1 -> A1 [dir=none, style=dotted];
    w2 -> A2 [dir=none, style=dotted];
    w3 -> C3 [dir=none, style=dotted];
    w4 -> A3 [dir=none, style=dotted];
    w5 -> C4 [dir=none, style=dotted];
    w6 -> C5 [dir=none, style=dotted];
    w7 -> A5 [dir=none, style=dotted];

    w1 [shape=box];
    w2 [shape=box];
    w3 [shape=box];
    w4 [shape=box];
    w5 [shape=box];
    w6 [shape=box];
    w7 [shape=box];

    w1 [label='4000', fillcolor='yellow3'];
    w2 [label='5500', fillcolor='pink'];
    w3 [label='4900', fillcolor='orange'];
    w4 [label='8000', fillcolor='red'];
    w5 [label='4300', fillcolor='orange'];
    w6 [label='2800', fillcolor='yellow'];
    w7 [label='3740', fillcolor='yellow3'];

    A1 [label='A'];
    A2 [label='A'];
    A3 [label='A'];
    A4 [label='A'];
    A5 [label='A'];
    A6 [label='A'];
    B1 [label='B'];
    B2 [label='B'];
    C1 [label='C'];
    C2 [label='C'];
    C3 [label='C'];
    C4 [label='C'];
    C5 [label='C'];
    C6 [label='C'];
    C7 [label='C'];
    D1 [label='D'];

  }")
graph.svg<-exportSVG(gph)
write(graph.svg, "C:/graph.svg")

這將生成一個標准的SVG文件,如下所示:

在此處輸入圖片說明

暫無
暫無

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

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