使用 networkDynamic and/or ndtv 控制动态顶点属性

Controlling dynamic vertex attributes using networkDynamic and/or ndtv

我正在研究政府机构如何随时间变化。计划是使用 ndtv 包来可视化更改。我有一个节点列表,其中列出了顶点 ID、机构名称、节点起点和节点终点:

nodelist <- read.csv("https://github.com/aterhorst/data/raw/master/nodelist.csv", header=T, stringsAsFactors = F)

和一个边列表显示开始,边的终点:

edgelist <- read.csv("https://github.com/aterhorst/data/raw/master/edgelist.csv", header=T, stringsAsFactors = F)

我可以很容易地创建网络对象:

nw <- network(edgelist,
              vertex.attr = nodelist[,c(1,2)],
              vertex.attrnames = c("vertex.id", "agency"), 
              directed = F)

nd <-networkDynamic(nw, 
                    edge.spells = edgelist[,c(3,4,2,1)],
                    vertex.spells=nodelist[,c(3,4,1)])

我可以根据边、顶点为网络设置动画没问题:

reconcile.vertex.activity(nd, mode = "match.to.edges")

filmstrip(nd, 
          displaylabels = FALSE, 
          frames = 5, 
          slice.par = list(start = 2014, end = 2019, interval = 1, aggregate.dur = 1, rule = 'any'))

render.d3movie(nd,
               filename = "~/owncloud/longspine/data/animation.html",
               displaylabels = FALSE,
               # This slice function makes the labels work
               vertex.tooltip = function(slice) {paste("<b>Agency:</b>", (slice %v% "agency"))})

这基本上显示了边和顶点如何随时间变化。接下来,我想按机构预算调整顶点大小。这每年都在变化。我应该怎么做?在线教程有点难以解释。在我的示例中,我们总共有 217 个代理机构。每个人都会有一个年度预算(如果它们存在于节点列表中的起点,终点)。任何提示或建议将不胜感激。

要设置动态顶点属性,您可以使用 activate.vertex.attribute() 函数来定义哪些顶点在多长时间内应具有哪些值。例如,要在顶点 1 上创建一个名为 'budget' 且 2014-2015 值为 10000 的动态属性:

    nd <-activate.vertex.attribute(nd,'budget',
                                  value=10000,
                                  onset=2014,
                                  terminus=2015,
                                  v=1)

您可能希望在创建对象时一次完成所有这些操作。如果您设置 nodelist 使其每年每个顶点一行,您应该能够使用 networkDynamic() 构造函数的 create.TEAs 选项来初始化具有属性 activity你需要的法术。因此,如果您的 nodelist 看起来像:


      vertex.id        agency portfolio      onset   terminus  budget
    1         1   AAF Company     FALSE 2014-07-01 2015-07-01   10000
    2         1   AAF Company     FALSE 2015-07-01 2016-07-01   10500
    ...

然后

    nd <-networkDynamic(nw, 
                    edge.spells = edgelist[,c(3,4,2,1)],
                    vertex.spells=nodelist[,c(3,4,1)],
                    create.TEAs=TRUE,
                    vertex.TEA.names='budget')

"Activating TEA Attributes" 上的 networkDynamic 包小插图中的部分应该有更多有用的信息 https://cran.r-project.org/web/packages/networkDynamic/vignettes/networkDynamic.pdf

然后您应该能够将动态顶点属性映射到 ndtv 中的动画图 属性(ndtv 将在每个时间点管理从动态属性到静态属性的转换正如它呈现的那样)

render.d3movie(nd,vertex.cex='budget')

除非这些组织有 异常 适度的预算,我猜你想使用 log() 预算或其他一些方式来转换原始预算数字或节点将大得难以想象。

还有一个教程对此进行了更深入的介绍,因为在时间 windows 中如何聚合值有一些必要的微妙之处:http://statnet.csde.washington.edu/workshops/SUNBELT/current/ndtv/ndtv_workshop.html#controlling-plot-properties-using-dynamic-attributes-teas

我设法让一些东西起作用。

require(sna)
require(tsna)
require(ndtv)
require(networkDynamic)
require(lubridate)

nodelist <- read.csv("https://github.com/aterhorst/data/raw/master/nodelist.csv", header=T, stringsAsFactors = F)
edgelist <- read.csv("https://github.com/aterhorst/data/raw/master/edgelist.csv", header=T, stringsAsFactors = F)
nodelist_expanded <- read.csv("https://github.com/aterhorst/data/raw/master/nodelist_expanded.csv", header=T, stringsAsFactors = F)

# onset date must be numeric (does not like date?)
nodelist$onset <- year(nodelist$onset)
nodelist$terminus <- year(nodelist$terminus)

# colour nodes by portfolio type
nodelist$col <- ifelse(nodelist$portfolio == T, "red", "blue")

nodelist_expanded$onset <- year(nodelist_expanded$onset)
nodelist_expanded$terminus <- year(nodelist_expanded$terminus)

# scale attributes
nodelist_expanded$log_appropriation <- log(nodelist_expanded$appropriation + 10) / 10
nodelist_expanded$log_ext_revenue <- log(nodelist_expanded$ext_revenue + 10) / 10

edgelist$onset <- year(edgelist$onset)
edgelist$terminus <- year(edgelist$terminus)

# create basic network object
nw <- network(edgelist[,c(2,3)],
          vertex.attr = nodelist[,c(1:3,6)],
          vertex.attrnames = c("vertex.id", "agency", "portfolio", "col"),
          directed = F)

# plot basic network object
plot(nw, vertex.col = "col")

# make dynamic network object
nd <-networkDynamic(nw,
                    edge.spells = edgelist[,c(4,5,3,2)],
                    vertex.spells = nodelist_expanded[,c(6,7,1,8,9)],
                    create.TEAs = TRUE,
                    vertex.TEA.names = c("log_appropriation", "log_ext_revenue"))

# reconcile things
reconcile.vertex.activity(nd, mode = "match.to.edges")

# make movie!
render.d3movie(nd,
               displaylabels = FALSE,
               vertex.col = "col",
               vertex.tooltip = function(slice) {
             paste("<b>Agency:</b>", (slice %v% "agency"))})