Finding the distance matrix using igraph - r

I have a network that is connected like the following:
library(igraph)
network <- graph_from_literal(1--2,2--3,3--4,4--5,3--6,6--7,3--8,8--9)
and have the distance between each segment
> data=data.frame(Origin=c(1,2,3,4,3,6,3,8), Destination=c(2,3,4,5,6,7,8,9), km=c(0.3,0.5,0.2,0.1,1,2,0.6,0.4))
> data
Origin Destination km
1 2 0.3
2 3 0.5
3 4 0.2
4 5 0.1
3 6 1.0
6 7 2.0
3 8 0.6
8 9 0.4
I would like to find the distance matrix between all points and I tried using
distMatrix <- shortest.paths(data, v=Origin(data), to=Destination(data))
but cannot make it work.
Thanks!

The distances() function will give you a distance matrix. By setting the edge weights, the distance matrix will include these weights in the calculation. In the code below, I create the graph from your dataset data, such that the edges are correctly ordered:
library("igraph")
data = data.frame(Origin=c(1,2,3,4,3,6,3,8), Destination=c(2,3,4,5,6,7,8,9),
km=c(0.3,0.5,0.2,0.1,1,2,0.6,0.4))
g = graph_from_edgelist(cbind(data$Origin, data$Destination))
E(g)
#> + 8/8 edges from 7ad6d28:
#> [1] 1->2 2->3 3->4 4->5 3->6 6->7 3->8 8->9
E(g)$weight = data$km
distances(g)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
#> [1,] 0.0 0.3 0.8 1.0 1.1 1.8 3.8 1.4 1.8
#> [2,] 0.3 0.0 0.5 0.7 0.8 1.5 3.5 1.1 1.5
#> [3,] 0.8 0.5 0.0 0.2 0.3 1.0 3.0 0.6 1.0
#> [4,] 1.0 0.7 0.2 0.0 0.1 1.2 3.2 0.8 1.2
#> [5,] 1.1 0.8 0.3 0.1 0.0 1.3 3.3 0.9 1.3
#> [6,] 1.8 1.5 1.0 1.2 1.3 0.0 2.0 1.6 2.0
#> [7,] 3.8 3.5 3.0 3.2 3.3 2.0 0.0 3.6 4.0
#> [8,] 1.4 1.1 0.6 0.8 0.9 1.6 3.6 0.0 0.4
#> [9,] 1.8 1.5 1.0 1.2 1.3 2.0 4.0 0.4 0.0
Created on 2021-09-06 by the reprex package (v2.0.1)

Perhaps we can try distances like below
> distances(
+ graph_from_data_frame(data, directed = FALSE),
+ weights = data$km
+ )
1 2 3 4 6 8 5 7 9
1 0.0 0.3 0.8 1.0 1.8 1.4 1.1 3.8 1.8
2 0.3 0.0 0.5 0.7 1.5 1.1 0.8 3.5 1.5
3 0.8 0.5 0.0 0.2 1.0 0.6 0.3 3.0 1.0
4 1.0 0.7 0.2 0.0 1.2 0.8 0.1 3.2 1.2
6 1.8 1.5 1.0 1.2 0.0 1.6 1.3 2.0 2.0
8 1.4 1.1 0.6 0.8 1.6 0.0 0.9 3.6 0.4
5 1.1 0.8 0.3 0.1 1.3 0.9 0.0 3.3 1.3
7 3.8 3.5 3.0 3.2 2.0 3.6 3.3 0.0 4.0
9 1.8 1.5 1.0 1.2 2.0 0.4 1.3 4.0 0.0

Related

How to use r to repeat a vector of sequence in descending and increasing order alternately?

I am new to R. I need to create a vector of length 37 with elements repeating the following pattern:
0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 1.5, 1.5, ... , 2.5, 2.5, 3.0, 3.0, 2.5, 2.5, 2.0, 2.0, ..., 0.5, 0.5, 0.0, 0.0, 0.5, 0.5, ...
The problem is, after creating the sequence, I do not know how to repeat it in the descending and increasing order alternately. Here is my code:
rep(seq(0.0,3.0,by = 0.5), each = 2, length = 37)
which only repeats the sequence in the general order. What should I supplement in my code to create a vector as required? Hope someone can help me solve this. Thank you so much!
You can do something like this:
f <- function(length.out) {
b = c(0, rep(seq(0.5, 2.5, 0.5), each=2), 3.0)
n=ceiling(length.out-2)/10
c(0, rep(c(b, rev(b)),n), 0)[1:length.out]
}
Now, just call the function, passing your desired length:
f(37)
[1] 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5 1.0
[30] 1.0 1.5 1.5 2.0 2.0 2.5 2.5 3.0
f(246)
[1] 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5
[29] 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5
[57] 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5
[85] 3.0 3.0 2.5 2.5 2.0 2.0 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5
[113] 2.0 2.0 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0 1.5 1.5
[141] 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0 1.5 1.5 1.0 1.0 0.5 0.5
[169] 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5
[197] 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5
[225] 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5 1.0 1.0
Now, call the function
EDIT:
Here's the shortest I can do:
rep(rep(c(0:6,5:1)/2,e=2),l=37)
[1] 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0
[19] 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5
[37] 3.0
I'm curious to see a better way than this:
a <- rep(seq(0.0,3.0,by = 0.5), each = 2) # go up
b <- rev(a[3:12]) # go down, w/o ends
c <- c(a,b) # combine
rep(c, length.out = 37) # repeat for 37 elements
[1] 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5 2.0
[10] 2.0 2.5 2.5 3.0 3.0 2.5 2.5 2.0 2.0
[19] 1.5 1.5 1.0 1.0 0.5 0.5 0.0 0.0 0.5
[28] 0.5 1.0 1.0 1.5 1.5 2.0 2.0 2.5 2.5
[37] 3.0
You can do:
mySeq <- seq(0.5,3.0,by = 0.5)
rep(c(0, mySeq, sort(mySeq[-6], decreasing = TRUE)), each = 2, length = 37)
Try this
rep(c(seq(0.0,3.0,by = 0.5),rep(seq(2.5,0.5,by = -0.5))), each = 2, length = 37)

Can't get data for all combinations

I have 31 possible scenarios for the value of the average and I would like to generate for each scenario samples but I do not get as much as I would like.
This is the scenarios
> scenari<-s*shift;scenari
Var1 Var2 Var3 Var4 Var5
2 1.5 0.0 0.0 0.0 0.0
3 0.0 1.5 0.0 0.0 0.0
4 1.5 1.5 0.0 0.0 0.0
5 0.0 0.0 1.5 0.0 0.0
6 1.5 0.0 1.5 0.0 0.0
7 0.0 1.5 1.5 0.0 0.0
8 1.5 1.5 1.5 0.0 0.0
9 0.0 0.0 0.0 1.5 0.0
10 1.5 0.0 0.0 1.5 0.0
11 0.0 1.5 0.0 1.5 0.0
12 1.5 1.5 0.0 1.5 0.0
13 0.0 0.0 1.5 1.5 0.0
14 1.5 0.0 1.5 1.5 0.0
15 0.0 1.5 1.5 1.5 0.0
16 1.5 1.5 1.5 1.5 0.0
17 0.0 0.0 0.0 0.0 1.5
18 1.5 0.0 0.0 0.0 1.5
19 0.0 1.5 0.0 0.0 1.5
20 1.5 1.5 0.0 0.0 1.5
21 0.0 0.0 1.5 0.0 1.5
22 1.5 0.0 1.5 0.0 1.5
23 0.0 1.5 1.5 0.0 1.5
24 1.5 1.5 1.5 0.0 1.5
25 0.0 0.0 0.0 1.5 1.5
26 1.5 0.0 0.0 1.5 1.5
27 0.0 1.5 0.0 1.5 1.5
28 1.5 1.5 0.0 1.5 1.5
29 0.0 0.0 1.5 1.5 1.5
30 1.5 0.0 1.5 1.5 1.5
31 0.0 1.5 1.5 1.5 1.5
32 1.5 1.5 1.5 1.5 1.5
and this is the function
genereting_fuction<-function(n){
for (i in 1:length(scenari)){
X1=rnorm(n)+scenari[i,1]
X4=rnorm(n)+scenari[i,4]
X2=X1*p12+std_e2*rnorm(n)+scenari[i,2]
X3=X1*p13+X4*p43+std_e3*rnorm(n)+scenari[i,3]
X5=X2*p25+X3*p35+std_e5*rnorm(n)+scenari[i,5]
sample=cbind(X1,X2,X3,X4,X5)
return(sample)
}
}
genereting_fuction(10)
I should get 31 samples of size 10X5 but I get only one sample
You are applying the for loop over return as well and eventually returning the sample corresponding to the last scenario only.
Try this :
genereting_fuction<-function(n){
sample <- list()
for (i in 1:nrow(scenari)){
X1=rnorm(n)+scenari[i,1]
X4=rnorm(n)+scenari[i,4]
X2=X1*p12+std_e2*rnorm(n)+scenari[i,2]
X3=X1*p13+X4*p43+std_e3*rnorm(n)+scenari[i,3]
X5=X2*p25+X3*p35+std_e5*rnorm(n)+scenari[i,5]
sample[[i]]=cbind(X1,X2,X3,X4,X5)
}
sample
}
The output will be a list and its ith element will be a sample corresponding to the ith scenario.

Using R, data.table, conditionally sum columns

I have a data table similar to this (except it has 150 columns and about 5 million rows):
set.seed(1)
dt <- data.table(ID=1:10, Status=c(rep("OUT",2),rep("IN",2),"ON",rep("OUT",2),rep("IN",2),"ON"),
t1=round(rnorm(10),1), t2=round(rnorm(10),1), t3=round(rnorm(10),1),
t4=round(rnorm(10),1), t5=round(rnorm(10),1), t6=round(rnorm(10),1),
t7=round(rnorm(10),1),t8=round(rnorm(10),1))
which outputs:
ID Status t1 t2 t3 t4 t5 t6 t7 t8
1: 1 OUT -0.6 1.5 0.9 1.4 -0.2 0.4 2.4 0.5
2: 2 OUT 0.2 0.4 0.8 -0.1 -0.3 -0.6 0.0 -0.7
3: 3 IN -0.8 -0.6 0.1 0.4 0.7 0.3 0.7 0.6
4: 4 IN 1.6 -2.2 -2.0 -0.1 0.6 -1.1 0.0 -0.9
5: 5 ON 0.3 1.1 0.6 -1.4 -0.7 1.4 -0.7 -1.3
6: 6 OUT -0.8 0.0 -0.1 -0.4 -0.7 2.0 0.2 0.3
7: 7 OUT 0.5 0.0 -0.2 -0.4 0.4 -0.4 -1.8 -0.4
8: 8 IN 0.7 0.9 -1.5 -0.1 0.8 -1.0 1.5 0.0
9: 9 IN 0.6 0.8 -0.5 1.1 -0.1 0.6 0.2 0.1
10: 10 ON -0.3 0.6 0.4 0.8 0.9 -0.1 2.2 -0.6
Using data.table, I would like to add a new column (using :=) called Total that would contain the following:
For each row,
if Status=OUT, sum columns t1:t4 and t8
if Status=IN, sum columns t5,t6,t8
if Status=ON, sum columns t1:t3 and t6:t8
The final output should look like this:
ID Status t1 t2 t3 t4 t5 t6 t7 t8 Total
1: 1 OUT -0.6 1.5 0.9 1.4 -0.2 0.4 2.4 0.5 3.7
2: 2 OUT 0.2 0.4 0.8 -0.1 -0.3 -0.6 0.0 -0.7 0.6
3: 3 IN -0.8 -0.6 0.1 0.4 0.7 0.3 0.7 0.6 1.6
4: 4 IN 1.6 -2.2 -2.0 -0.1 0.6 -1.1 0.0 -0.9 -1.4
5: 5 ON 0.3 1.1 0.6 -1.4 -0.7 1.4 -0.7 -1.3 1.4
6: 6 OUT -0.8 0.0 -0.1 -0.4 -0.7 2.0 0.2 0.3 -1.0
7: 7 OUT 0.5 0.0 -0.2 -0.4 0.4 -0.4 -1.8 -0.4 -0.5
8: 8 IN 0.7 0.9 -1.5 -0.1 0.8 -1.0 1.5 0.0 -0.2
9: 9 IN 0.6 0.8 -0.5 1.1 -0.1 0.6 0.2 0.1 0.6
10: 10 ON -0.3 0.6 0.4 0.8 0.9 -0.1 2.2 -0.6 2.2
I am fairly new to data.table (currently using version 1.9.6) and would like to try for a solution using efficient data.table syntax.
I think doing it one by one, as suggested in comments, is perfectly fine, but you can also create a lookup table:
cond = data.table(Status = c("OUT", "IN", "ON"),
cols = Map(paste0, 't', list(c(1:4, 8), c(5,6,8), c(1:3, 6:8))))
# Status cols
#1: OUT t1,t2,t3,t4,t8
#2: IN t5,t6,t8
#3: ON t1,t2,t3,t6,t7,t8
dt[cond, Total := Reduce(`+`, .SD[, cols[[1]], with = F]), on = 'Status', by = .EACHI]
# ID Status t1 t2 t3 t4 t5 t6 t7 t8 Total
# 1: 1 OUT -0.6 1.5 0.9 1.4 -0.2 0.4 2.4 0.5 3.7
# 2: 2 OUT 0.2 0.4 0.8 -0.1 -0.3 -0.6 0.0 -0.7 0.6
# 3: 3 IN -0.8 -0.6 0.1 0.4 0.7 0.3 0.7 0.6 1.6
# 4: 4 IN 1.6 -2.2 -2.0 -0.1 0.6 -1.1 0.0 -0.9 -1.4
# 5: 5 ON 0.3 1.1 0.6 -1.4 -0.7 1.4 -0.7 -1.3 1.4
# 6: 6 OUT -0.8 0.0 -0.1 -0.4 -0.7 2.0 0.2 0.3 -1.0
# 7: 7 OUT 0.5 0.0 -0.2 -0.4 0.4 -0.4 -1.8 -0.4 -0.5
# 8: 8 IN 0.7 0.9 -1.5 -0.1 0.8 -1.0 1.5 0.0 -0.2
# 9: 9 IN 0.6 0.8 -0.5 1.1 -0.1 0.6 0.2 0.1 0.6
#10: 10 ON -0.3 0.6 0.4 0.8 0.9 -0.1 2.2 -0.6 2.2

R sequence from matrix

I have matrix like
> brdrs <- matrix(c(-1,-0.2,0.2,3),ncol=2,byrow=TRUE)
> brdrs
[,1] [,2]
[1,] -1.0 -0.2
[2,] 0.2 3.0
I want to make sequence, based on this matrix. First column is the start of interval, second- the end. Each row is interval of one sequence.
For example it would be: from -1.0 to -0.2 AND from 0.2 to 3.0 by 0.1.
Is it possible without loops?
Thanks
You could use this :
unlist(sapply(1:nrow(brdrs),function(x){seq(brdrs[x,1],brdrs[x,2],0.1)}))
[1] -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
[18] 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6
[35] 2.7 2.8 2.9 3.0
Like Ananda Mahto said in the comment, you should specify the increment of the sequence. Here, I used 0.1

apply function to vector with condition to introduce 0 (and do not apply function) for negative values?

I need to apply function to vector b3, but insert 0 (and do not apply function) when b3 < 0.
> b3
[1] 1.5 0.5 5.5 0.5 9.5 8.5 4.5 3.5 3.5 3.5 1.5 -0.5 1.5 5.5 9.5
[16] 5.5 2.5 1.5 2.5 3.5 9.5 -0.5 4.5 2.5 1.5 4.5 -0.5 -0.5 1.5 0.5
> unlist(lapply(b3, function(x) {seq(from = 0.5, to = x)}))
[1] 0.5 1.5 0.5 0.5 1.5 2.5 3.5 4.5 5.5 0.5 0.5 1.5 2.5 3.5 4.5
[16] 5.5 6.5 7.5 8.5 9.5 0.5 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 0.5
[31] 1.5 2.5 3.5 4.5 0.5 1.5 2.5 3.5 0.5 1.5 2.5 3.5 0.5 1.5 2.5
[46] 3.5 0.5 1.5 0.5 -0.5 0.5 1.5 0.5 1.5 2.5 3.5 4.5 5.5 0.5 1.5
[61] 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5 0.5 1.5 2.5 3.5 4.5 5.5 0.5
[76] 1.5 2.5 0.5 1.5 0.5 1.5 2.5 0.5 1.5 2.5 3.5 0.5 1.5 2.5 3.5
[91] 4.5 5.5 6.5 7.5 8.5 9.5 0.5 -0.5 0.5 1.5 2.5 3.5 4.5 0.5 1.5
[106] 2.5 0.5 1.5 0.5 1.5 2.5 3.5 4.5 0.5 -0.5 0.5 -0.5 0.5 1.5 0.5
gives me close to what I need, but I have problems with negatives values of b3. So how to introduce 0 each times function get to negative value in b3 ? Here's what I came with :
> unlist(lapply(b3, function(x) {ifelse(x>0,seq(from = 0.5, to = x),0)}))
[1] 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.0 0.5 0.5 0.5 0.5 0.5 0.5 0.5
[20] 0.5 0.5 0.0 0.5 0.5 0.5 0.5 0.0 0.0 0.5 0.5
works for negative values, but my function doesn't behave as expected...
Sorry for the previous answer, I read too quickly. You probably just want to use if rather than ifelse:
#Small, similar example
b3 <- c(1.5,0.5,5.5,-2.5,1.5)
unlist(lapply(b3, function(x) {if (x < 0) 0 else seq(from = 0.5, to = x)}))
[1] 0.5 1.5 0.5 0.5 1.5 2.5 3.5 4.5 5.5 0.0 0.5 1.5

Resources