атрибут веса ребер не работает в пакете `DiagrammeR` R - PullRequest
1 голос
/ 26 мая 2020

Я пытаюсь добавить некоторые атрибуты ребер в граф GraphViz, используя пакет DiagrammeR в R. В частности, я хочу добавить атрибуты arrowhead и weight, но в граф добавляется только первый. но не последнее. Приведенный ниже пример не настоящий, а его супер-уменьшенная версия для воспроизводимости и ясности.

library(tidyverse)
library(DiagrammeR)
# create nodes
nd <- tibble(
  label =  c("A", "B", "C", "D"), 
  rank  =  c("1", "0", "2", "2")
)

node <- create_node_df(
  n     = nrow(nd),
  label = nd$label,
  id    =  c(1:nrow(nd)),
  # rank  = nd$rank
)

# create edges
ed <- tribble(
  ~from, ~to, ~arrowhead, ~weight,
  1,     2,   'normal',       "5",
  1,     3,   'normal',       "1",
  3,     4,   'normal',       "1",
  3,     2,   'normal',       "1"
)
edge <- create_edge_df(
  from      = ed$from,
  to        = ed$to,
  arrowhead = ed$arrowhead,
  weight    = ed$weight
)


# create graph
graph <-
  create_graph(
    nodes_df   = node,
    edges_df   = edge) %>%
  add_global_graph_attrs(
    attr       = "overlap",
    value      = "false",
    attr_type  = "graph") %>%
  add_global_graph_attrs(
    attr       = "layout",
    value      = "dot",
    attr_type  = "graph")

Тем не менее, когда я генерирую код dot, атрибут weight не является частью ребер, а arrowhead является.

graph %>%
  generate_dot() %>%
  cat()

#> digraph {
#> 
#> graph [layout = 'dot',
#>        outputorder = 'edgesfirst',
#>        bgcolor = 'white',
#>        overlap = 'false']
#> 
#> node [fontname = 'Helvetica',
#>       fontsize = '10',
#>       shape = 'circle',
#>       fixedsize = 'true',
#>       width = '0.5',
#>       style = 'filled',
#>       fillcolor = 'aliceblue',
#>       color = 'gray70',
#>       fontcolor = 'gray50']
#> 
#> edge [fontname = 'Helvetica',
#>      fontsize = '8',
#>      len = '1.5',
#>      color = 'gray80',
#>      arrowsize = '0.5']
#> 
#>   '1' [label = 'A'] 
#>   '2' [label = 'B'] 
#>   '3' [label = 'C'] 
#>   '4' [label = 'D'] 
#> '1'->'2' [arrowhead = 'normal'] 
#> '1'->'3' [arrowhead = 'normal'] 
#> '3'->'4' [arrowhead = 'normal'] 
#> '3'->'2' [arrowhead = 'normal'] 
#> }

Я также пробовал добавить атрибут, используя set_edge_attrs(), но он все еще не работает.

graph <- graph %>% 
  set_edge_attrs(edge_attr = "weight", 
                 values = "5", 
                 from = 1, 
                 to = 2
                 )
# digraph {
#   
#   graph ...
#  {trimmed output}
#
#   '1'->'2' [arrowhead = 'normal'] 
#   '1'->'3' [arrowhead = 'normal'] 
#   '3'->'4' [arrowhead = 'normal'] 
#   '3'->'2' [arrowhead = 'normal'] 
# }

В конце концов, мне пришлось изменить код dot вручную (см. Ниже), но это не идеально, учитывая, что мне нужно создавать несколько диаграмм из информации в фреймах данных.

graph2 <- "digraph {

graph [layout = 'dot',
       outputorder = 'edgesfirst',
       bgcolor = 'white',
       overlap = 'false']

node [fontname = 'Helvetica',
      fontsize = '10',
      shape = 'circle',
      fixedsize = 'true',
      width = '0.5',
      style = 'filled',
      fillcolor = 'aliceblue',
      color = 'gray70',
      fontcolor = 'gray50']

edge [fontname = 'Helvetica',
     fontsize = '8',
     len = '1.5',
     color = 'gray80',
     arrowsize = '0.5']

  '1' [label = 'A'] 
  '2' [label = 'B'] 
  '3' [label = 'C'] 
  '4' [label = 'D'] 
'1'->'2' [arrowhead = 'normal', weight = 5] 
'1'->'3' [arrowhead = 'normal', weight = 0] 
'3'->'4' [arrowhead = 'normal', weight = 0] 
'3'->'2' [arrowhead = 'normal', weight = 0]  
}
"
grViz(graph2)

Я очень ценю любую помощь.

Спасибо. С уважением,

1 Ответ

1 голос
/ 26 мая 2020

Я не уверен, является ли это ошибкой или "вес" намеренно игнорируется, но в любом случае виновником является вспомогательная функция в DiagrammeR, которая генерирует вектор разрешенных атрибутов, а generate_dot() разрешает только атрибуты из этот вектор.

# DiagrammeR/R/utils.R
gv_edge_attributes <- function() {

  c("style", "penwidth", "color", "arrowsize",
    "arrowhead", "arrowtail",
    "fontname", "fontsize", "fontcolor",
    "len", "tooltip", "URL",
    "label", "labelfontname", "labelfontsize",
    "labelfontcolor", "labeltooltip", "labelURL",
    "edgetooltip", "edgeURL",
    "headtooltip", "headURL",
    "headclip", "headlabel", "headport",
    "tailtooltip", "tailURL",
    "tailclip",  "taillabel", "tailport",
    "dir", "decorate")
}

Если вы добавите «вес» в этот список - или измените generate_dot, чтобы разрешить все атрибуты без проверок - ваш пример будет работать нормально.

...