Skip to content

Instantly share code, notes, and snippets.

@briatte
Last active September 9, 2015 10:54
Show Gist options
  • Save briatte/89ba28f6956bbcf1ad23 to your computer and use it in GitHub Desktop.
Save briatte/89ba28f6956bbcf1ad23 to your computer and use it in GitHub Desktop.
differences in edge assignment methods of R network package
# issue when assigning a vector of edge values:
# x %e% "y" = 1:z ## does not assign 1:z, creates duplicates
# set.edge.value(x, "y", 1:z) ## does not assign 1:z, creates duplicates
# set.edge.attribute(x, "y", 1:z) ## assigns 1:z, as expected
# using version 1.12.0
library(network)
# minimal reprex
m = matrix(rbinom(100,1,.4),10,10)
diag(m) = 0
n = network(m, directed = FALSE)
e = network.edgecount(n)
# issue [1]: assign vector of sequential ids with %e%
n %e% "edge.id" = paste0("id", 1:e)
all(n %e% "edge.id" == 1:e) # bug: FALSE
any(duplicated(n %e% "edge.id")) # bug: TRUE
# bugfix [1]: issue solved by using set.edge.attribute
set.edge.attribute(n, "edge.id", 1:e)
all(n %e% "edge.id" == 1:e) # TRUE
any(duplicated(n %e% "edge.id")) # FALSE
# issue [2]: copy vector of sequential ids with %e%
n %e% "edge.copy" = n %e% "edge.id"
all(n %e% "edge.copy" == n %e% "edge.id") # bug: FALSE
# bugfix [2]: issue solved by using set.edge.attribute
set.edge.attribute(n, "edge.copy", n %e% "edge.id")
all(n %e% "edge.copy" == n %e% "edge.id") # TRUE
# works as expected
x = set.edge.attribute(n, "edge.id", 1:e)
x = n %e% "edge.id"
all(x == 1:e) # TRUE
# unexpected result
y = set.edge.value(n, "edge.id", 1:e)
y = n %e% "edge.id"
all(y == 1:e) # bug: FALSE
any(duplicated(y)) # bug: TRUE
# not due to copying the result with %e%
z = set.edge.value(n, "edge.id", 1:e)
z = get.edge.value(n, "edge.id")
all(z == 1:e) # bug: FALSE
any(duplicated(z)) # bug: TRUE
@briatte
Copy link
Author

briatte commented Sep 8, 2015

Text below by the creator of the network package.


The %e%<- and set.edge.value functions do not assign values in the same order as set.edge.attribute. (In particular, note that %e%<- is just a front-end to set.edge.value.) As noted in the help page, set.edge.value assigns values in adjacency matrix order, while set.edge.attribute assigns them in edge ID order; the latter is more general, but the former is often more convenient for dyadic networks.

Here's an example of the use of the edge value setting mechanism:

m <- rgraph(5)
net <- network(m)
net[,]
  1 2 3 4 5
1 0 0 1 1 0
2 0 0 0 0 1
3 0 1 0 0 1
4 0 1 0 0 0
5 1 1 1 1 0
net%e%"snd"<-row(m)
net%e%"rec"<-col(m)
as.sociomatrix(net,"snd")
  1 2 3 4 5
1 0 0 1 1 0
2 0 0 0 0 2
3 0 3 0 0 3
4 0 4 0 0 0
5 5 5 5 5 0
as.sociomatrix(net,"rec")
  1 2 3 4 5
1 0 0 3 4 0
2 0 0 0 0 5
3 0 2 0 0 5
4 0 2 0 0 0
5 1 2 3 4 0

Note that the edge value routine expects a full (adjacency) matrix of values - if it gets a vector, it will attempt to coerce it into an appropriately sized matrix, which means that values may not end up where you expect. In particular, if you only pass the values for observed edges (i.e., leaving out the structural zeros), R will repeat your input vector until it fills out an n x n matrix (which is unlikely to be a salutary outcome).

To sum up, %e%<- and set.edge.value are convenience functions whose purpose is to streamline the very common use case in which one has a valued adjacency matrix and wishes to use it to set edge values for a network object. set.edge.attribute is fully general - and much more efficient for very large, sparse graphs - but requires one to know the IDs of the edges one wants to modify (and is hence less convenient for most users). Both types of functions can be used for similar purposes, but they take very different inputs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment