Changing edge color based on attribute - r

I'm working on the visual representation of a network on R software, using the igraph package.
I have a data set with links between all the nodes and, for each link/edge, the district that they are assign to.
So, I would like to change the edge color of each edge, based on each district they are assign to. The table above shows the structure of the table.
nodei
nodej
depot1
depot2
4
5
1
0
In this case the link (4-5) is assigned to depot1, so the edge color of the edge should be green, for example.

Here is an exmaple that edges associated with 1 will be colored in "red", and "green" otherwise:
g <- make_ring(5)
g %>%
set_edge_attr(
name = "color",
value = c("green", "red")[1 + (rowSums(ends(., E(.)) == "1") > 0)]
) %>%
plot()
In your case, you could replace "1" by "depot1" and have a try.

I tried to understand your question, I created a node type to color the edges and nodes.
library(igraph)
data <- read.table(text = "
N D type
1 6 A
3 7 B
7 8 A
4 5 B
7 10 A
4 6 B
1 7 A
6 8 B
7 9 B
6 10 A ", header=T )
nodes <- data.frame(id=unique(c(data$N, data$D)) )
nodes$type <- c("A","B") # this if for the layout
nodes$x <- c(1,3,7,4,7, 4, 1,6,7,6)
nodes$y <- c(6,7,8,5,10,,5, 7,8,9,10)
nodes
G <- graph_from_data_frame(dd, vertices = nodes )
V(G)$color <- ifelse( V(G)$type == "A", "red", "green")
E(G)$color <- ifelse( E(G)$type == "A", "red","green")
edge_attr(G)
vertex_attr(G)
plot(G)

Related

how to convert a node list to an edge list in igraph?

I have a empty graph and need to plot the graph based on the convex hull with inner verticies.
My attemp is:
library(igraph)
set.seed(45)
n = 10
g <- graph.empty(n)
xy <- cbind(runif(n), runif(n))
vp <- convex_hull(xy)$resverts + 1
#[1] 8 10 7 2 1
## convert node_list to edge_list
plot(g, layout=xy)
Expected result in right figure.
Question. How to convert a node list to an edge list in igraph??
You can use add_edges along with embed
g2 <- g %>%
add_edges(c(t(embed(vp, 2)), vp[1], vp[length(vp)])) %>%
as.undirected()
and plot(g2, layout = xy) in turn gives
convex_hull does not output a node list in the same sense that an igraph object has a node list. In this case, vp is the sequence of indices so in order to create an edge list, you just need to have the from vertex be going to the next vertex in the sequence. This can be accomplished with dplyr::lead using the first vertex as the default to create a circuit.
data.frame(
from = vp,
to = dplyr::lead(vp, 1, default = vp[1])
)
#> from to
#> 1 8 10
#> 2 10 7
#> 3 7 2
#> 4 2 1
#> 5 1 8
Try this.
## create graph.
vids <- as.character(c(8, 10, 7, 2, 1))
g <- make_graph(c(), length(vids))
V(g)$name <- vids
## and connect the dots.
g2 <- g + path(c(vids, vids[1]))
g2

R lattice -- unexpected legend

I want to graphically compare carbon pools under different forms of land use.
I am reading in my data,
later I remove a factor level.
However, when I display the data the legend does not work.
The first legend symbol has no label, and
the deleted factor (SPEZIALKULTUREN) is still shown.
how can I control the legend?
A sample of the data is shown below
enter image description here
enter image description here
agdata <- read.csv("C:/Jandl/LfdProjekte/2017FAO/2020Paper/Agdata.csv", header = FALSE, sep = ";", dec = ",")
colnames(agdata) <- c("State","AgType","Cpool")
agdata$Cpool <- as.numeric(agdata$Cpool)
levels(agdata$AgType)[levels(agdata$AgType)=="ACKERLAND"] <- "crop"
levels(agdata$AgType)[levels(agdata$AgType)=="ALMEN"] <- "alpine meadow"
levels(agdata$AgType)[levels(agdata$AgType)=="EXTENSIVES GRÜNLAND *"] <- "extens grassland"
levels(agdata$AgType)[levels(agdata$AgType)=="INTENSIVES GRÜNLAND**"] <- "intens grassland"
levels(agdata$AgType)[levels(agdata$AgType)=="WEINGARTEN***"] <- "vineyard"
#dropping SPEZIALKULTUREN
agdata <- subset(agdata,agdata$AgType !="SPEZIALKULTUREN")
agdata <- subset(agdata,agdata$State !="")
agdata <- subset(agdata,agdata$State !="Wien")
library(lattice)
colors = c("lightsalmon3", "lightgoldenrod2", "cadetblue4", "yellow", "red", "blue")
barchart(
data = agdata,
origin = 0,
Cpool ~ State,
groups = AgType ,
xlab = list (
label = "State",
font = 2,
cex = 1),
ylab= list (
label = "C pool t/ha",
font = 2,
cex = 1),
#ylim=c(0,25),
labels = TRUE,
auto.key = list(space="top", columns= 3),
par.settings = list(superpose.polygon = list(col = colors)))
I am not sure, but it happened to me sometimes that, when using the subset function, removed factors remain empty in the dataframe and will occasionally show on some plots. For example, consider this simple dataset named "myexample":
> myexample
var1 var2
1 1 a
2 5 a
3 6 b
4 3 b
5 7 c
Now I can subset it to keep only rows where var2 is either a or b
> myexample2<-subset(myexample, var2=="a" | var2=="b")
> myexample2
var1 var2
1 1 a
2 5 a
3 6 b
4 3 b
> levels(myexample2$var2)
[1] "a" "b" "c"
It will look like "c" was dropped, but it is still there. To properly get rid of it, you can use the function droplevels()
> myexample2<-droplevels(myexample2)
> myexample2
var1 var2
1 1 a
2 5 a
3 6 b
4 3 b
> levels(myexample2$var2)
[1] "a" "b"
And now it is really gone. Maybe give it a try and see if at least the removed factor is no longer in the plot.

Match vertex and edge color in igraph

I have a large data set that I want to represent with a network graph using igraph. I just don't understand how to get the colors right. Is it possible to get an igraph plot with edge having the same color as vertex color? I my example below, I would like to color vertex and edges according to the status 'sampled' or 'unsampled'. An other problem is that all the edge do not appear on the igraph, and I don't understand why
My code so far is:
d <- data.frame(individual=c(1:10), mother_id = c(0,0,0,0,0,1,3,7,6,7), father_id = c(0,0,0,0,0,4,1,6,7,6) , generation = c(0,0,0,0,0,1,1,2,2,2), status=c("sampled","unsampled","unsampled","sampled",'sampled',"sampled","unsampled","unsampled","sampled",'sampled'))
#Just some settings for layout plot
g <- d$generation
n <- nrow(d)
pos <- matrix(data = NA, nrow = n, ncol = 2)
pos[, 2] <- max(g) - g
pos[, 1] <- order(g, partial = order(d$individual, decreasing = TRUE)) - cumsum(c(0, table(g)))[g + 1]
#Plotting the igraph
G <- graph_from_data_frame(d)
plot(G, rescale = T, vertex.label = d$individual, layout = pos,
edge.arrow.mode = "-",
vertex.color = d$status,
edge.color = d$status,
asp = 0.35)
My question is somewhat similar to this question, but I would like to do it with igraph package.
Ggraph node color to match edge color
Thanks for your help
if you plot(G) you will see that the graph from data frame object is not what you expect, most likely. That is why you dont see all edges (i.e the column father_id is not used at all).
By default igraph takes the first column as "from" and the second one as "to". That is why you see 1to0, 2to0 and so on.
You can fix this by passing in two objects, one with the edges and their attributes, and one with the nodes and their attributes.
It is not so clear to me where the edges should be. However, your code should look something like this:
dd <- read.table(text = "
from to type
1 6 A
3 7 B
7 8 A
6 9 B
7 10 A
4 6 B
1 7 A
6 8 B
7 9 B
6 10 A ", header=T )
nodes <- data.frame(id=unique(c(dd$from, dd$to)) )
nodes$type <- sample(LETTERS[1:2], 8, replace = T )
nodes$x <- c(8,3,5,7,1,2,4,10) # this if for the layout
nodes$y <- c(1, 2, 4, 5, 6, 8, 5, 7)
nodes
id type x y
1 1 B 8 1
2 3 A 3 2
3 7 B 5 4
4 6 A 7 5
5 4 A 1 6
6 8 B 2 8
7 9 A 4 5
8 10 A 10 7
G <- graph_from_data_frame(dd, vertices = nodes ) # directed T or F?
V(G)$color <- ifelse( V(G)$type == "A", "pink", "skyblue")
E(G)$color <- ifelse( E(G)$type == "A", "pink", "skyblue")
edge_attr(G)
vertex_attr(G)
plot(G)

Extract edges between community nodes and other nodes

Suppose we have a simple weighted network on which we perform some sort of community detection. Next we extract particular community and the final task is to extract all edges between nodes of this community and all other nodes.
Below I pasted the toy code.
# Create toy graph
library(igraph)
set.seed(12345)
g <- make_graph("Zachary")
# Add weights to edges
E(g)$weight <- sample(x = 1:10, size = ecount(g), replace = TRUE)
# Run community detection
cl <- cluster_louvain(g)
There are 5 nodes which belong to community #1, 12 nodes which belong to community #2, etc.
> table(membership(cl))
1 2 3 4
5 12 2 15
Now we extract community #1:
g1 <- induced_subgraph(g, which(cl$membership == 1))
Question: how to find edges which connect nodes in community #1 with all other nodes (excluding edges which define community #1)?
Start by getting all edges based in your community:
all_edges <- E(g)[inc(V(g)[membership(cl) == 1])]
all_edges
+ 10/78 edges:
[1] 1-- 5 1-- 6 1-- 7 1--11 5-- 7 5--11 6-- 7 6--11 6--17 7--17
Then, filter out the ones that are completely internal (both vertices are in the community):
all_edges_m <- get.edges(g, all_edges) #matrix representation
all_edges[!(
all_edges_m[, 1] %in% V(g)[membership(cl) == 1] &
all_edges_m[, 2] %in% V(g)[membership(cl) == 1]
)] # filter where in col1 and col2
+ 4/78 edges:
[1] 1-- 5 1-- 6 1-- 7 1--11

Plot conditional colors based on rows

I have two data.frames called outlier and data.
outlier just keeps row numbers which needs to be coloured.
data has 1000 data.
It has two columns called x and y.
If row number exists in outliers I want dots in plot to be red, otherwise black
plot(data$x, data$y, col=ifelse(??,"red","black"))
Something should be in ?? .
Hi this way works for me using ifelse, let me know what you think:
outlier <- sample(1:100, 50)
data <- data.frame(x = 1:100, y = rnorm(n = 100))
plot(
data[ ,1], data[ ,2]
,col = ifelse(row.names(data) %in% outlier, "red", "blue")
,type = "h"
)
I think this can be accomplished by creating a new color column in your data frame:
data$color <- "black"
Then set the outliers to a different value:
data[outlier,"color"] <- "red"
I dont have your exact data but I think I got something similar to what you wanted using the following:
outlier <- c(1, 2, 7, 9)
data <- data.frame(x=c(1,2,3,4,5,6,7,8,9,10),
y=c(1,2,3,4,5,6,7,8,9,10))
data$color <- "black"
data[outlier,"color"] <- "red"
data
x y color
1 1 1 red
2 2 2 red
3 3 3 black
4 4 4 black
5 5 5 black
6 6 6 black
7 7 7 red
8 8 8 black
9 9 9 red
10 10 10 black
Finally plot using the new value in data:
plot(data$x, data$y, col=data$color)
Results in:

Resources