12 Temporal
In the previous chapter we built a graph with dynamic edges. Let’s build a fully dynamic graph where both nodes and edges appear when they are first created.
12.1 Collect
We again collect tweets in a slightly different manner but feel free to use data from a previous chapter. We specify type
as mixed
in order to get a mix of popular and recent tweets.
# TK <- readRDS(file = "token.rds")
tweets <- search_tweets("#rstats filter:mentions", n = 300, token = TK, include_rts = FALSE, type = "mixed")
## Searching for tweets...
## Finished collecting tweets!
12.2 Build
We build the graph as we did in the previous chapter.
net <- tweets %>%
gt_edges(screen_name, mentions_screen_name, created_at) %>%
gt_nodes() %>%
gt_dyn() %>%
gt_collect()
12.3 Visualise
Again, we unpack the network and prepare nodes and edges for our visualisation. Then we define a rescale
functiion to ensure our treatment of the date time columns are consistent across nodes and edges.
c(edges, nodes) %<-% net
#' @param x Date time column.
#' @param t Number of milliseconds to rescale to.
rescale <- function(x, t){
x <- as.numeric(x)
x <- (x - min(x)) / (max(x) - min(x))
x <- x * t
return(x)
}
rtweet returns date time but sigmajs expects milliseconds; it needs to be converted.
Next we prepare the data, we define the t
argument of our rescale
function defined above as a constant so as to make sure we apply the same scale to both nodes and edges.
library(dplyr)
T <- 10000
lockBinding("T", globalenv())
nodes <- nodes %>%
nodes2sg() %>%
mutate(
start = rescale(start, T)
) %>%
select(id, label, size, start)
edges <- edges %>%
mutate(
id = 1:n(),
created_at = as.numeric(created_at),
created_at = rescale(created_at, T)
) %>%
select(id, source, target, created_at)
Now the actual visualisation, then again, we set cumsum = FALSE
, and add a button (linked to two events add_nodes
and add_edges
) to let you trigger the visualisation. before then you should see a blank canvas.
sigmajs() %>%
sg_add_nodes(nodes, start, id, label, size, cumsum = FALSE) %>%
sg_add_edges(edges, created_at, id, source, target, cumsum = FALSE) %>%
sg_button(c("add_nodes", "add_edges"), "Start")
We forgot the layout and we do not color the nodes, let’s compute the layout and the clusters to color nodes.
nodes <- sg_get_layout(nodes, edges)
nodes <- sg_get_cluster(
nodes,
edges,
colors = c(
"#0084b4",
"#00aced",
"#1dcaff",
"#c0deed"
)
)
## Found # 105 clusters
sigmajs() %>%
sg_add_nodes(nodes, start, id, label, size, color, x, y, cumsum = FALSE) %>%
sg_add_edges(edges, created_at, id, source, target, cumsum = FALSE) %>%
sg_button(c("add_nodes", "add_edges"), "Start")
So we transformed our date time to milliseconds and rescaled to span 10 seconds. The problem with this is that we, in a way, lose track of time in the visualisation itself. It’d be great to add a ticker to display, say, the date.
Let’s explain how this is done in sigmajs; we simply create a table that maps dates to our milliseconds delay
. To do so we extract the dates from our net
object, we then rescale those dates just like we did for the nodes and edges.
dates <- as.Date(net$nodes$start)
ticker <- dplyr::tibble(
dates = dates,
delay = rescale(dates, T)
) %>%
arrange(delay)
head(ticker)
dates | delay |
---|---|
2019-04-12 | 0.000 |
2019-04-13 | 3447.215 |
2019-04-14 | 8240.184 |
Now, how do we use this mapping table in sigmajs?
sigmajs() %>%
sg_add_nodes(nodes, start, id, label, size, color, x, y, cumsum = FALSE) %>%
sg_add_edges(edges, created_at, id, source, target, cumsum = FALSE) %>%
sg_progress(ticker, delay, dates, cumsum = FALSE) %>%
sg_settings(
edgeColor = "default",
defaultEdgeColor = "#d3d3d3"
) %>%
sg_button(c("add_nodes", "add_edges", "progress"), "Start")
We use the sg_progress
function to which we pass both the ticker columns’ variables and we tie that event to our button.