not.a.hackerman
not.a.hackerman

Reputation: 87

ggnetwork graph does not accurately plot values to colour nodes

I am trying to make a graph with ggplot2 and ggnetwork. I have a two dimensional lattice grid, an adjacency matrix, and I want to illustrate certain values by colour coding.

Unfortunately i can either get the network going, or the accurate colour coding, but not both at the same time.

Here is my code and sample data to reproduce my problem:

library(network)
library(ggnetwork)
library(ggplot2)


#SAMPLE DATA
adj_matrix <- matrix(c(0, 1, 0, 1, 1, 0, 0, 0, 0,
                       1, 0, 1, 1, 1, 1, 0, 0, 0,
                       0, 1, 0, 0, 1, 1, 0, 0, 0,
                       1, 1, 0, 0, 1, 0, 1, 1, 0,
                       1, 1, 1, 1, 0, 1, 1, 1, 1,
                       0, 1, 1, 0, 1, 0, 0, 1, 1,
                       0, 0, 0, 1, 1, 0, 0, 1, 0,
                       0, 0, 0, 1, 1, 1, 1, 0, 1,
                       0, 0, 0, 0, 1, 1, 0, 1, 0), nrow = 9, ncol = 9, byrow = TRUE)

grid_coords <- matrix(NA, nrow=3 * 3, ncol=2)
cell_size <- 1
origin_x <- 1
origin_y <- 1
k <- 1
for (i in 1:3) {
  for (j in 1:3) {
    x <- (j-1) * cell_size + origin_x
    y <- (i-1) * cell_size + origin_y
    grid_coords[k,] <- c(x, y)
    k <- k + 1
  }
}

R <- c(1.0000000, 0.5723928, 0.1447857, 1.4276072, 1.0000000, 0.5723928, 1.8552143, 1.4276072, 1.0000000)


#GENERATING GRAPH
gra <- network.initialize(nrow(grid_coords), directed=F)
gra <- network.adjacency(adj_matrix, gra)
n <- ggnetwork(gra, layout=grid_coords, arrow.gap=0)

r_i <- data.frame(R=R, X=n$x[1:nrow(grid_coords)], Y=n$y[1:nrow(grid_coords)], xend=rep(0, nrow(grid_coords)), yend=rep(0, nrow(grid_coords)))

ggplot(n, aes(x = x, y = y, xend = xend, yend = yend)) +
  geom_edges(color = "grey80") +
  geom_point(size=5, col="grey80") +
  geom_point(size=3.5, col="white") +
  geom_point(dat=r_i, aes(x=X, y=Y, color = R), size=3.5) +
  scale_colour_gradient(low="steelblue3", high='firebrick3', name=expression(bold(R)[ix]), limit=c(min(R),max(R)), na.value = "white") +
  theme(panel.background = element_blank(),
        axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank())

The code above will create the network, but won't apply the correct colouring to the nodes.

enter image description here

However, by hashing out one line the colouring issue can be solved, but the network connecting the nodes is not generated.

gra <- network.initialize(nrow(grid_coords), directed=F)
#gra <- network.adjacency(adj_matrix, gra)
n <- ggnetwork(gra, layout=grid_coords, arrow.gap=0)

r_i <- data.frame(R=R, X=n$x[1:nrow(grid_coords)], Y=n$y[1:nrow(grid_coords)], xend=rep(0, nrow(grid_coords)), yend=rep(0, nrow(grid_coords)))

ggplot(n, aes(x = x, y = y, xend = xend, yend = yend)) +
  geom_edges(color = "grey80") +
  geom_point(size=5, col="grey80") +
  geom_point(size=3.5, col="white") +
  geom_point(dat=r_i, aes(x=X, y=Y, color = R), size=3.5) +
  scale_colour_gradient(low="steelblue3", high='firebrick3', name=expression(bold(R)[ix]), limit=c(min(R),max(R)), na.value = "white") +
  theme(panel.background = element_blank(),
        axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank())

Here is the figure with the correct colouring: enter image description here

I think it might have to do with something about the synchronisation of the nodes, but havent been able to crack it so far.

Thanks for considering this problem :)

EDIT: After Allan's solution to my original question i am wondering if there is a way to create a function which synchs up all possible node networks. Heres the sample data for a triangle: Thanks again:)

#SAMPLE DATA OF NOT SYMMETRICAL LATTICE


adj_matrix2 <- matrix(c( 0,  1,  0,  0,  0,  0,  0,  0, 1, 0,
                        1,  0,  1,  0,  0,  0,  0,  1, 1, 1,
                        0,  1,  0,  1,  1,  1,  0,  0, 0, 1,
                        0,  0,  1,  0,  1,  0,  0,  0, 0, 0,
                        0,  0,  1,  1,  0,  1,  0,  0, 0, 1,
                        0,  0,  1,  0,  1,  0,  1,  1, 0, 1,
                        0,  0,  0,  0,  0,  1,  0,  1, 0, 1,
                        0,  1,  0,  0,  0,  1,  1,  0, 1, 1,
                        1,  1,  0,  0,  0,  0,  0,  1, 0, 1,
                        0,  1,  1,  0,  1,  1,  1,  1, 1, 0), nrow = 10, ncol = 10, byrow = TRUE)

Xchords <- c(1,2,3,4,4,4,4,3,2,3)
Ychords <- c(1,2,3,4,3,2,1,1,1,2)

grid_coords2 <- (cbind(Xchords, Ychords))


R2 <- c(2.057551,  2.057551,  2.057551,  2.057551,  2.057551,  2.057551,  2.057551,  2.057551,  2.057551, 10.517957 )

And here is the image with incorrect colouring:

enter image description here

Upvotes: 2

Views: 88

Answers (1)

Allan Cameron
Allan Cameron

Reputation: 173793

The problem is nothing to do with your plotting code - you simply haven't defined the node data frame correctly (examine the x and y co-ordinates of r_i).

If you do:

r_i <- data.frame(R = R, 
                  X = rep(sort(unique(n$x)), 3),
                  Y = rep(sort(unique(n$y)), each = 3))

And plot with

ggplot(n, aes(x = x, y = y, xend = xend, yend = yend)) +
  geom_edges(color = "grey80") +
  geom_point(size = 5, color = "grey80") +
  geom_point(aes(x = X, y = Y, color = R), data = r_i,  
             size = 3.5, inherit.aes = FALSE) +
  scale_colour_gradient(low = "steelblue3", high = 'firebrick3', 
                        name = expression(bold(R)[ix])) +
  theme(panel.background = element_blank(),
        axis.title       = element_blank(),
        axis.text        = element_blank(),
        axis.ticks       = element_blank())

You get this:

enter image description here

Upvotes: 1

Related Questions