0

I am trying to assign the same color gradient to both, edges and vertices on igraph using R. The gradient should color from low to high counts in the V(data_graph)$Counts portion.

Some reproducible data:

library(igraph) 
data <- data.frame(Country = c("Africa", "Argentina", "Bolivia", "Chile", "France", "Guam", "Poland", "Greenland", "Switzerland", "UK", "US"), 
               Counts = c(2,2,8,1,5,3,3,15, 15,30,35), 
               Pillar = c(rep("SoS", 4), rep("CNES", 4), rep("STE", 3)))

data_center <- setNames(data.frame("c", 1, "Sos"), names(data))
data_vtx <- rbind(data_center, data)
data_rel <- data.frame(from = head(data_vtx$Country, 1), 
                    to = data_vtx$Country[2:12])

which produces the following graph:

data_graph <- graph_from_data_frame(data_rel,  directed = FALSE, data_vtx)

plot(data_graph, 
 layout = layout.fruchterman.reingold(data_graph),
 vertex.size = round(V(data_graph)$Counts/1.5, 2), 
 vertex.label.color = "black",
 edge.curved = 0.3)

However, next I would like to apply the same color gradient to both, the vertex and the edges based on the V(data_graph)$Counts. What I need is something similar to the scale_color_gradient2 command from ggplot2.

Example:

scale_color_gradient2(low = “blue”, mid = “yellow”, high = “red”, midpoint = mean(V(data_graph)$Counts))

The closest I have found is the following post: How can I assign color range to edges in igraph plot in R based on edge attributes? This post was very informative on making a color gradient in igraph, but each edge there has it's own color. Because some of the V(data_graph)$Counts are the same, they should be colored the same in the color gradient.

Any help will be greatly appreciated!

Purrsia
  • 712
  • 5
  • 18
  • You are plotting `data_graph` but your example code does not produce that object - nor any graph. Please add the missing code. – G5W Dec 23 '22 at 23:02
  • 1
    Thank you G5W for pointing that out. I have edited to include the line of code that was missing. – Purrsia Dec 23 '22 at 23:12

2 Answers2

2

You can use colorRampPalette to create the color ramp from blue to yellow to red. Then use the Counts to select the colors for both the vertices and the edges. I used a somewhat arbitrary way of selecting the colors, but you can adjust the aesthetics to your taste.

CRP = colorRampPalette(c("blue", "yellow", "red"))

plot(data_graph, 
 layout = layout.fruchterman.reingold(data_graph),
 vertex.size = round(V(data_graph)$Counts/1.5, 2), 
 vertex.label.color = "black",
 vertex.color = CRP(19)[round(V(data_graph)$Counts/2)+1],
 edge.color   = CRP(19)[round(V(data_graph)$Counts/2)+1],
 edge.curved = 0.3)

Graph with colored edges

r2evans
  • 141,215
  • 6
  • 77
  • 149
G5W
  • 36,531
  • 10
  • 47
  • 80
  • Thank-you for this. Yes, this does show a gradient, as expected. However, I am looking for a solution similar to `scale_color_gradient2` (above post) where I can use mean(V(data_graph)$Counts) as the midpoint of the gradient - so all circles below the mean show a gradient from blue to yellow and above the mean shows yellow to red. Lastly, because some of the V(data_graph)$Counts are the same, they should be colored the same in the color gradient. This method gives the colors for each circle a gradient from blue to yellow to red. It does not take the mean(V(data_graph)$Counts into account. – Purrsia Dec 24 '22 at 22:10
  • Any ideas on how this can be achieved? – Purrsia Dec 24 '22 at 22:20
0

Assuming your palette is known. If not see Gradient of n colors ranging from color 1 and color 2. Add the Palette to the data and data_center data frames. Add vertex and edge colors to the plot() statement.

library(igraph)

data <- data.frame(Country = c("Africa", "Argentina", "Bolivia", "Chile", "France", "Guam", "Poland", "Greenland", "Switzerland", "UK", "US"), 
               Counts = c(2,2,8,1,5,3,3,15, 15,30,35), 
               Pillar = c(rep("SoS", 4), rep("CNES", 4), rep("STE", 3)),
              Palette = rainbow(11)  # <<< 
         )

data_center <- setNames(data.frame("c", 1, "Sos", "black"), names(data)) # <<< center color  is black
data_vtx <- rbind(data_center, data)
data_rel <- data.frame(from = head(data_vtx$Country, 1), 
                         to = data_vtx$Country[-1]
            )
                    
data_graph <- graph_from_data_frame(data_rel,  directed = FALSE, data_vtx)

set.seed(202212)
plot(data_graph, layout = layout_as_star(data_graph),
 vertex.size        = round(V(data_graph)$Counts/1.5, 2), 
 vertex.color       = data_vtx$Palette,
 vertex.label.color = "black",
 edge.width         = 3,
 edge.curved        = 0.3,
 edge.color         = data_vtx$Palette[-1]
) 

To make the palette, and assuming G5W's suggestion.

CRP          <- colorRampPalette(c("blue", "yellow", "red"))
cols         <- CRP(max(data$Counts) + 1)
data$Palette <- cols[data$Counts + 1] # instead of rainbow(11)

## Or use rank instead of population.
data$Palette <- CRP(nrow(data))[rank(data$Counts, ties.method="first")]
clp
  • 1,098
  • 5
  • 11
  • Thank-you for this. No, unfortunately I don't know my gradient. However, what I'm looking for is a way to do a gradient similar to `ggplot2` `scale_color_gradient2` command where I can choose a low, midpoint, high gradient (above post). I would then use mean(V(data_graph)$Counts) as the midpoint of the gradient - so all circles below the mean show a gradient from blue to yellow and above the mean shows yellow to red. – Purrsia Dec 24 '22 at 22:18
  • If you move this additional information to the question, you are more likely to get more useful answers. Having found the answer, you can move the results to the data frames as described. – clp Dec 25 '22 at 09:24
  • clp - I have always had that information on the question. Please see above question. – Purrsia Dec 27 '22 at 00:27
  • I found your comment about the color yellow as the center point very helpful. I have expanded my answer to include making the gradient. – clp Dec 27 '22 at 18:26