Apply an index command on a matrix of lists - r

I have a matrix that contains lists containing shortest path sequences of an igraph object.
I want to turn this matrix into an igraph.es(edge sequence).
sample:
library(igraph)
data <- data.frame(from =c(1, 2, 3, 4, 5, 1),
to =c(4, 3, 4, 5, 6, 5),
weight=c(0.2,0.1,0.5,0.7,0.8,0.2))
g <- graph.data.frame(data, directed=FALSE)
sp <- sapply(data, function(x){shortest_paths(g, from = x, to = V(g)[x],output = "epath")})
sp is now a matrix. We can subset it with indexing:
x<-sp[[2]][[2]]
will turn x to an igraph::edge_sequence.
I'm looking for an apply command to turn all path_sequences of sp into edge_sequences. Thank you in advance.
EDIT:
I managed to unlist the first layer of the list.
sp<-flatten(sp)
So we just need a simple index.
Can I just use a for loop now?
Something like:
for(i in sp){ result[i]<- sum(E(g)$weight[sp[[i]])}
unfortunately this doesn't give me the desired output..

Related

How to create a 3D array from 2D matrices in R?

I would like to create a 3D array based on a couple of 2D matrices in R, but I have no idea. Let's say we have the following three matrices:
matrix1 <- matrix(1:1, nrow = 5, ncol = 5)
matrix2 <- matrix(2:2, nrow = 5, ncol = 5)
matrix3 <- matrix(3:3, nrow = 5, ncol = 5)
I would like to know how to create one [1:3, 1:5, 1:5] array, as a combination of the three matrices. Thank you!
We can concatenate the matrixes together into a vector, use array to construct a 3D array with specified dim
ar1 <- array(c(matrix1, matrix2, matrix3), c(5, 5, 3))

How to create chain from pairs in R

edit: added current solution
I am dabbling with the Travelling Salesman Problem and am using a solver to calculate the most optimal tour. The output of my linear solver gives me a table with arches in a route, however to plot the tour I require vector with all the locations chained in the right order. Is there an elegant way to chain these arches into a single tour?
One solution would be a series of (nested) joins/matches, however that is not an elegant solution in my opinion.
# output of solver (where i = 'from' and j = 'to')
solution = data.frame(i = c(6, 4, 10, 7, 1, 9, 3, 2, 8, 5),
j = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
# transformation
??
# required output
tour = c(6, 1, 5, 10, 3, 7, 4, 2, 8, 9)
So the output I am looking for is a single chain of connected arches (from i to j) in the tour.
My current solution uses for loops and match and looks as follows:
# number of cities to visit
nCities = length(solution)
# empty matrix
tour = matrix(0, nCities, 2)
#first location to visit picked manually
tour[1, ] = solution[1, ]
# for loop to find index of next arch in tour
for(k in 2:nCities){
ind = match(tour[k - 1, 2], solution[, 1])
tour[k, ] = solution[ind, ]
}
# output 'tour' is the solution but then sorted.
# I then take only the first column which is the tour
tour = tour[1, ]
However, it looks clunky and as I try to avoid for loops as much as possible I am not to happy with it. Also, my suspicion is that there are more elegant solutions out there, preferably using base R functions.

R remove duplicate spatial points according an attribute

In R I have a SpatialPointsDataFrame whit duplicated point (coordinates and attributes), I would like to remove all point with same data ...
I have find in the sp package the remove.duplicates() function but it seems to remove only on location ... Is there another way?
thank you
E.
Would something like this work?
library(sp)
pts <- SpatialPoints(cbind(c(1, 1, 1, 2, 3, 4), c(1, 1, 1, 4, 2, 4)))
pts <- SpatialPointsDataFrame(pts, data=data.frame(id = c(1, 2, 2, 3, 4, 5)))
## All points
pts
## No spatial duplicates
remove.duplicates(pts)
## No duplicates in attributes
pts[which(!duplicated(pts$id)), ]
## Combination
pts[which(!duplicated(as.data.frame(pts))), ]

For loop over selected rows

I am new to R (or any programming language) I want to run a for loop along a selected rows of a Matrix, say 3,5,6,8. I know how to do it for a continuous range. How can I do it?
try this:
my_mat <- matrix(1:20, ncol = 2)
my_seq <- c(3, 5, 6, 8)
for(i in my_seq) {
print(my_mat[i, ])
}

Arrange elements on a matrix according to rowSums + short 'apply' Q

Greetings,
My goal is to create a Markov transition matrix (probability of moving from one state to another) with the 'highest traffic' portion of the matrix occupying the top-left section. Consider the following sample:
inputData <- c(
c(5, 3, 1, 6, 7),
c(9, 7, 3, 10, 11),
c(1, 2, 3, 4, 5),
c(2, 4, 6, 8, 10),
c(9, 5, 2, 1, 1)
)
MAT <- matrix(inputData, nrow = 5, ncol = 5, byrow = TRUE)
colnames(MAT) <- c("A", "B", "C", "D", "E")
rownames(MAT) <- c("A", "B", "C", "D", "E")
rowSums(MAT)
I wan to re-arrange the elements of this matrix such that the elements with the largest row sums are placed to the top-left, in descending order. Does this make sense? In this case the order I'm looking for would be B, D, A, E, C Any thoughts?
As an aside, here is the function I've written to construct the transition matrix. Is there a more elegant way to do this that doesn't involve a double transpose?
TMAT <- apply(t(MAT), 2, function(X) X/sum(X))
TMAT <- t(TMAT)
I tried the following:
TMAT <- apply(MAT, 1, function(X) X/sum(X))
But my the custom function is still getting applied over the columns of the array, rather than the rows. For a check try:
rowSums(TMAT)
colSums(TMAT)
Row sums here should equal 1...
Many thanks in advance,
Aaron
Use rowSums and colSums more!
The first problem can be done with simple:
MAT[order(rowSums(MAT),decreasing=T),]
The second with:
MAT/rep(rowSums(MAT),nrow(MAT))
this is a bit hacky, but becomes obvious if you recall that matrix is also a by-column vector.
Taking also recycling into account it can be also done just by:
MAT/rowSums(MAT)
For your first request, this gets the desired descending reordering by row sums:
MAT[rev(order(rowSums(MAT))), ]
And this gets your TMAT in one step. The apply function returns a series of vectors and the column major ordering of matrices will transpose the results from what beginning users of R expect.
> TMAT <- t(apply(MAT, 1, function(X) X/sum(X)) )
> rowSums(TMAT)
A B C D E
1 1 1 1 1

Resources