0

我正在研究政府机构如何随时间变化。计划是使用 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 个代理机构。每个人都有一个年度预算(如果它们按开始存在,则在节点列表中存在)。任何提示或建议将不胜感激。

4

2 回答 2

1

我设法得到一些工作。

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"))})
于 2019-06-13T06:37:29.600 回答
0

to set up dynamic vertex attributes you can use the activate.vertex.attribute() function to define which vertices should have what values for what duration. For example, to create a dynamic attribute on vertex 1 named 'budget' with value 10000 from 2014-2015:

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

Likely you would want to do this all at once when creating the object. If you set up your nodelist so that it has one row per vertex per year, you should be able to use the create.TEAs option of the networkDynamic() constructor to initialize the object with the attribute activity spells you need. So if your nodelist looks like:


      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
    ...

then

    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')

The section in the networkDynamic package vignette on "Activating TEA Attributes" should have more helpful info https://cran.r-project.org/web/packages/networkDynamic/vignettes/networkDynamic.pdf

You should then be able to map the dynamic vertex attribute to an animation plot property in ndtv (ndtv will manage the conversion from dynamic to static attribute at each time point as it renders)

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

Unless these organizations have unusually modest budgets, I'm guessing you'd want to use the log() of the budget or some other way to transform the raw budget numbers or the nodes will be unimaginably big.

There is also a tutorial that covers this in more depth, as there is some necessary subtlety in how the aggregation of values in time windows work: http://statnet.csde.washington.edu/workshops/SUNBELT/current/ndtv/ndtv_workshop.html#controlling-plot-properties-using-dynamic-attributes-teas

于 2019-05-29T04:53:41.337 回答