R remove duplicate spatial points according an attribute - r

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))), ]

Related

How to switch every two elements in a vector in R?

For example I have a vector as follows:
FOL.2. FOL TAL.2. TAL BOR.2. BOR HAD.2. HAD ITA.2. ITA NOR.2. NOR
I need the vector to be as follows:
FOL FOL.2. TAL TAL.2. BOR BOR.2. HAD HAD.2. ITA ITA.2. NOR NOR.2.
I tried sort(myvector) but it doesn't work. Basically I need to switch the positions of every two elements in the vector.Any advice is appreciated.
Another solution
x[1:length(x) + c(1, -1)]
The operation in [] converts 1, 2, 3, 4, 5, 6 to 2, 1, 4, 3, 6, 5.
One option is to create a matrix and then coerce
c(matrix(v1, nrow = 2)[2:1,])
#[1] "FOL" "FOL.2." "TAL" "TAL.2." "BOR" "BOR.2." "HAD" "HAD.2." "ITA" "ITA.2." "NOR" "NOR.2."
data
v1 <- scan(text = "FOL.2. FOL TAL.2. TAL BOR.2. BOR HAD.2. HAD ITA.2. ITA NOR.2. NOR", what = "")

Apply an index command on a matrix of lists

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..

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.

Appropriate method for transition function in gdistance

The following code is an example for the transition function from the pdf manual for gdistance:
library(raster)
library(gdistance)
r <- raster(nrows=6, ncols=7, xmn=0, xmx=7, ymn=0, ymx=6, crs="+proj=utm +units=m")
r[] <- c(2, 2, 1, 1, 5, 5, 5,
2, 2, 8, 8, 5, 2, 1,
7, 1, 1, 8, 2, 2, 2,
8, 7, 8, 8, 8, 8, 5,
8, 8, 1, 1, 5, 3, 9,
8, 1, 1, 2, 5, 3, 9)
T <- transition(r, function(x) 1/mean(x), 8)
# 1/mean: reciprocal to get permeability
T <- geoCorrection(T)
c1 <- c(5.5,1.5)
c2 <- c(1.5,5.5)
#make a SpatialLines object for visualization
sPath1 <- shortestPath(T, c1, c2, output="SpatialLines")
plot(r)
lines(sPath1)
#make a TransitionLayer for further calculations
sPath2 <- shortestPath(T, c1, c2)
plot(raster(sPath2))
My specific interest is in this line:
T <- transition(r, function(x) 1/mean(x), 8)
Because I've come across numerous examples of people doing the following:
T <- transition(1/r, mean, 8)
As far as I can tell, this is the difference between 1/mean(x) and mean(1/x), which are not equivalent.
To verify this, I ran both versions of the transition function using the above code from the gdistance manual, and got these two very different plots:
And using costDistance(T, c1, c2) I got a distance of 21.1 for the first, and 13.6 for the second.
Clearly, these are very different results. So, my question is, what is the correct method for creating a TransitionLayer object from a cost matrix/layer/raster?
This is indeed an important difference. Take a look at the Wikipedia article on the harmonic mean for more info.
In the example, the values in the input raster are costs. So the correct way is to take the arithmetic mean of the cost first and then take the reciprocal of that to get the conductance. The traveller experiences half of the cost of the origin cell and half of the cost of the destination cell, (cost1 + cost2)/2.
So 1/mean(x) is correct for this case.
If the input raster has conductance values, the other function is correct: mean(1/x).

Re-ordering bars in R's barplot()

What I want to achieve is exactly the same that was already asked here (and specifically using R's base graphics, not packages like ggplot or lattice): Ordering bars in barplot()
However, the solutions proposed there do not seem to work for me. What I need to is the following. Suppose I have this:
num <- c(1, 8, 4, 3, 6, 7, 5, 2, 11, 3)
cat <- c(letters[1:length(num)])
data <- data.frame(num, cat)
If I generate a barplot using barplot(data$num), here is what I get:
Now, I want to reorder the bars according to data$cat. Following the link I mentioned above, I tried the accepted answer but got an error:
num2 <- factor(num, labels = as.character(cat))
Error in factor(num, labels = as.character(cat)) : invalid 'labels'; length 10 should be 1 or 9
Then I also tried the other answer there:
num <- as.factor(num)
barplot(table(num))
But here is what I got:
So, in this particular case of mine, which is slightly different from that question, how should I order the barplot so the bars are defined by data$num but ordered according to data$cat?
you can use ggplot to do this
library("ggplot2")
num <- c(1, 8, 4, 3, 6, 7, 5, 2, 11, 3)
cat <- c(letters[1:10])
data <- data.frame(num, cat)
ggplot(data,aes(x= reorder(cat,-num),num))+geom_bar(stat ="identity")
The result is as shown below
Using base functions
df <- data[order(data$num,decreasing = TRUE),]
barplot(df$num,names.arg = df$cat)
I get the following,
num <- c(1, 8, 4, 3, 6, 7, 5, 2, 11, 3)
cat <- c(letters[1:10])
data <- data.frame(num, cat)
barplot(data[order(data[,1],decreasing=TRUE),][,1],names.arg=data[order(data[,1],decreasing=TRUE),][,2])
The above code uses the order() function twice (see comments, below). To avoid doing this the results of the ordered data.frame can be stored in a new data.frame and this can be used to generate the barplot.
num <- c(1, 8, 4, 3, 6, 7, 5, 2, 11, 3)
cat <- c(letters[1:10])
data <- data.frame(num, cat)
data2 <- data[order(data[,1],decreasing=TRUE),]
barplot(data2[,1],names.arg=data2[,2])
Alternatively, you can also use the following if you don't want to put your data in a new dataframe. Just a little simpler.
barplot(sort(data$num, decreasing = TRUE))

Resources