I would like to extract the polygon ID in which a point is located. I have tried multiple solutions but I could not figure out how to do it. Currently my code is the following:
r1<-raster(xmn=-111.4567,
xmx=136.841,
ymn=-94.39192,
ymx=123.5581,
res=50)
r1 = rasterToPolygons(r1)
d = cbind("x" = 7.36459732, "y"= 30.4465762)
extract(r1,d)
EDIT1:
If I get the grid coordinates from the raster, polygon ID of d should be 13 (as d is between -36.45 & 13.54 in x axis and between -1.44 and 48.55)
r1<-raster(xmn=-111.4567,
xmx=136.841,
ymn=-94.39192,
ymx=123.5581,
resolution=50)
cells<-cellFromRowColCombine(r1, 1:dim(r1)[1],1:dim(r1)[2])
coord_grid<-data.frame(xyFromCell(r1,cells),id=cells)
Thanks in advance for your help.
Here the solution I found: cellFromXY(r1, d)
Related
I was trying to make a raster image from an irregularly spaced point database. The data looks like-
> head(s100_ras)
x y z
1 267573.9 2633781 213.29545
2 262224.4 2633781 69.78261
3 263742.7 2633781 51.21951
4 259328.4 2633781 301.98413
5 264109.8 2633781 141.72414
6 255094.8 2633781 88.90244
I want these 'z' values within a mesh which I created by
# Create a fine mesh grid
my_mesh=expand.grid(seq(min(s100_ras$Y),max(s100_ras$Y),l=100),
seq(min(s100_ras$X),max(s100_ras$X),l=100))
I also want the z-values to be assigned as 'NA' for those mesh points that are outside the data points. The points over the mesh looks like this: https://drive.google.com/file/d/0B6GUNg-8d30vYzlwTkhvaHBFTnc/edit?usp=sharing
when I plot
plot(my_mesh)
points(s100_ras$Y, s100_ras$X, pch="*", col='blue')
The problem is that I'm not sure how to build on this, the following steps don't work because my mesh grid and data points are not of the same scale!!
library(rgdal)
library(raster)
xyz<-cbind(my_mesh, s100_ras)
r <- rasterFromXYZ(xyz)
image(r)
If I try to make a raster just by using the data points (without any mesh), R throws an error since my data is irregularly spaced!
library(sp)
s100_ras <- data.frame(expand.grid(x = s100_ras$Y, y = s100_ras$X),
z = as.vector(s100_ras$mean))
coordinates(s100_ras) <- ~x+y
proj4string(s100_ras) <- CRS("+proj=utm +zone=46 +datum=WGS84")
gridded(s100_ras) = TRUE
suggested tolerance minimum: 0.916421
Error in points2grid(points, tolerance, round) :
dimension 1 : coordinate intervals are not constant
Moreover, I was trying to play with 'rasterize' function (for irregular grids) of 'raster package', but couldn't get a way with it :(. I know how to interpolate and make a regular grid, but for the sake of originality, I want to AVOID interpolation. Is it possible to make a raster of irregularly spaced data points without idw or kriging methods? Thanks in advance.
The clear-cut solution to the answer has been provided by Robert here: https://gis.stackexchange.com/questions/79062/how-to-make-raster-from-irregular-point-data-without-interpolation
I would like to create a spatial grid with hexagonal cells using WGS84 coordinates (ie cells defined by 2 coordinates X=Latitude and Y=Longitude)
So, this is what I was thinkin about :
library(ggplot2);library(hexbin)
X<-seq(-10,20,by=0.1) # create coordinates vectors X and Y
Y<-seq(35,65,by=0.1)
z<-rnorm(301,0.5,1)
df<-as.data.frame(cbind(X,Y,z)) # create data frame with a z value for each cells (X,Y)
pl<-ggplot2(data=mat,aes(x=X,y=Y,z=z))+stat_summury_hex(fun=function(x) sum(x))
plot(pl)
But doing this does not provide what I wanted.
So, my question is : how to do a spatial grid with hexagonal cells using lat/lon coordinates ?
And second question : how to create a grid centered from one point (that would represent the centroid, and not the left bottom corner as usual?)
If I understand properly, you're looking for expand.grid():
xy <- expand.grid(X=X,Y=Y)
z<-rnorm(nrow(xy),0.5,1)
df<-as.data.frame(cbind(xy,z)) # create data frame with a z value for each cells (X,Y)
head(df)
pl<-ggplot(data=df,aes(x=X,y=Y,z=z))+stat_summary_hex(fun=function(x) sum(x))
plot(pl)
As for the second question, I'm not sure, but since all hexagons are the same size and will require the same operation to center, you can shift them uniformly by changing X and Y appropriately. Perhaps this can also be done via arguments also, not sure.
[[Edit July 23]]
second question was how to get a data.frame of hex coordinates. Took some digging, but here's an example:
library(hexbin)
coords <- hcell2xy( hexbin(x=X,y=Y))
head(coords)
x y
1 -10.0 35.00000
2 -9.5 35.86603
3 -8.5 35.86603
4 -9.0 36.73205
5 -8.0 36.73205
6 -7.5 37.59808
hcell2xy() is the key function called by ggplot2, and you may need to be explicit about specifying the argument xbins, which is determined automatically inside ggplot2, but appears to default to 30 in both cases.
[[Edit 3, to include z level]]
This is an answer to the comment asking for z levels as well. Ripped from ggplot2:::hexBin
hb <- hexbin(x=X,y=Y)
# Convert to data frame
data.frame(
hcell2xy(hb),
count = hb#count,
density = hb#count / sum(hb#count, na.rm=TRUE)
)
You can choose whether to use count or density for colors later, but warning: those are different from your z variable fed to ggplot2. If you'd like to summarize based on some other statistic, then I suggest you also look into the guts of those functions to see how things are passed around. That's what I've been doing.
I apologize in advance if my code looks very amateurish.
I'm trying to assign quadrants to 4 measurement stations approximately located on the edges of a town.
I have the coordinates of these 4 stations:
a <- c(13.2975,52.6556)
b <- c(14.0083,52.5583)
c <- c(13.3722,52.3997)
d <- c(12.7417,52.6917)
Now my idea was to create lines connecting the north-south and east-west stations:
line.1 <- matrix(c(d[1],b[1],d[2],b[2]),ncol=2)
line.2 <- matrix(c(a[1],c[1],a[2],c[2]),ncol=2)
Plotting all the stations the connecting lines looks allright, however not very helpful for analyzing it on a computer.
So I calculated the eucledian vectors for the two lines:
vec.1 <- as.vector(c((b[1]-d[1]),(b[2]-d[2])))
vec.2 <- as.vector(c((c[1]-a[1]),(c[2]-a[2])))
which allowed me to calculate the angle between the two lines in degrees:
alpha <- acos((vec.1%*%vec.2) / (sqrt(vec.1[1]^2+vec.1[2]^2)*
sqrt(vec.2[1]^2+vec.2[2]^2)))) * 180/pi
The angle I get for alpha is 67.7146°. This looks fairly good. From this angle I can easily calculate the other 3 angles of the intersection, however I need values relative to the grid so I can assign values from 0°-360° for the wind directions.
Now my next planned step was to find the point where the two lines intersect, add a horizontal and vertical abline through that point and then calculate the angle relative to the grid. However I can't find a proper example that does that and I don't think I have a nice linear equation system I could solve.
Is my code way off? Or maybe anyone knows of a package which could help me? It feels like my whole approach is a bit wrong.
Okay I managed to calculate the intersection point, using line equations. Here is how.
The basic equation for two points is like this:
y - y_1 = (y_2-y_1/x_2-x_1) * (x-x_1)
If you make one for each of the two lines, you can just substitute the fractions.
k.1 <- ((c[2]-a[2])/(c[1]-a[1]))
k.2 <- ((b[2]-d[2])/(b[1]-d[1]))
Reshaping the two functions you get a final form for y:
y <- (((-k.1/k.2)*d[2]+k.1*d[1]-k.1*c[1]+d[2])/(1-k.1/k.2))
This one you can now use to calculate the x-value:
x <- ((y-d[2])+d[1]*k.2)/k.2
In my case I get
y = 52.62319
x = 13.3922
I'm starting to really enjoy this program!
Wikipedia has a good article on finding the intersection between two line segments with an explicit formula. However, you don't need to know the point of intersection to calculate the angle to the grid (or axes of coordinate system.) Just compute the angles from your vec.1 and vec.2 to the basis vectors:
e1 <- c(1, 0)
e2 <- c(0, 1)
as you have done.
I want to draw a polygonal map in R (R3.0.2) and am getting nowhere. my polygon data is:
1768233.661.5912880.909
1767890.645,5912896.291
1767796.816,5913007.04
1767764.514,5913082.411
1767813.736,5913165.474
1767964.478,5913137.786
1768067.537,5913062.415
1768112.144,5913080.873
1768149.061,5913113.175
1768185.163,5913095.389
1768234.212,5913088.382
1768197.425,5913007.801
1768435.163,5912936.284
1768435.163,5912903.982
1768358.254,5912873.218
and I'm Ok getting it into R, but then I need to enter northing, easting for the window which is not working - when I input:
mydata <- read.table("treePolygon.csv", header = TRUE)
attach(mydata)
X <- ppp(Easting, Northing, c(1767750.7261, 1768447.9275), c(5912848.3905, 5913186.4806))
I get:
The following object is masked from mydata (position 3):
X1768233.661.5912880.909
The following object is masked from mydata (position 4):
X1768233.661.5912880.909
The following object is masked from mydata (position 5):
X1768233.661.5912880.909
I'm really new at this and quite lost.
If you've copied it exactly, the problem might be that your first data pair is separated by a period instead of a comma.
So first of all fix the comma. Second, your data has to actually have a header. This works:
library(spatstat)
mydata <- read.csv(header=T,text="Easting,Northing
1768233.661,5912880.909
1767890.645,5912896.291
1767796.816,5913007.04
1767764.514,5913082.411
1767813.736,5913165.474
1767964.478,5913137.786
1768067.537,5913062.415
1768112.144,5913080.873
1768149.061,5913113.175
1768185.163,5913095.389
1768234.212,5913088.382
1768197.425,5913007.801
1768435.163,5912936.284
1768435.163,5912903.982
1768358.254,5912873.218")
X <- with(mydata,ppp(Easting,
Northing,
c(1767750.7261, 1768447.9275), c(5912848.3905, 5913186.4806)))
X
# planar point pattern: 15 points
# window: rectangle = [1767750.7, 1768447.9] x [5912848, 5913186] units
plot(X)
Using attach(...) is generally not recommended - at causes all kinds of problems unless you remember to detach(...)
Thanks for putting me on the right track!
I finally drew a polygonal window using the example on p40 of Intro. to spatstat, Baddeley & Turner, for spatstat 1.8-6:
tab <- read.table(file="C:/N/0Random/0 TestData/fieldtrees.tab")
bdry <- scan("C:/N/0Random/0 TestData/field.tab", what=list(x=0,y=0))
plot(owin(poly=bdry))
I did have to swap the order of the points as R couldn't use them to write the polygon.
I'm now going to carry on with p40 of Intro. to spatstat, and ultimately hope to use Michael Bedward's Circle Packing with R to fill my space with different diameter circles.
I've been looking for a solution to convert cartesian coordinates (lat, long) that I have to polar coordinates in order to facilitate a simulation that I want to run, but I haven't found any questions or answers here for doing this in R. There are a number of options, including the built in function cart2pol in Matlab, but all of my data are in R and I'd like to continue getting comfortable working in this framework.
Question:
I have lat/long coordinates from tagging data, and I want to convert these to polar coordinates (meaning jump size and angle: http://en.wikipedia.org/wiki/Polar_coordinate_system) so that I can then shuffle or bootstrap them (haven't decided which) about 1,000 times, and calculate the straight-line distance of each simulated track from the starting point. I have a true track, and I'm interested in determining if this animal is exhibiting site affinity by simulating 1,000 random tracks with the same jump sizes and turning angles, but in completely different orders and combinations. So I need 1,000 straight-line distances from the origin to create a distribution of distances and then compare this to my true data set's straight-line distance.
I'm comfortable doing the bootstrapping, but I'm stuck at the very first step, which is converting my cartesian lat/long coordinates to polar coordinates (jump size and turning angle). I know there are built in functions to do this in other programs such as Matlab, but I can't find any way to do it in R. I could do it manually by hand in a for-loop, but if there's a package out there or any easier way to do it, I'd much prefer that.
Ideally I'd like to convert the data to polar coordinates, run the simulation, and then for each random track output an end point as cartesian coordinates, lat/long, so I can then calculate the straight-line distance traveled.
I didn't post any sample data, as it would just be a two-column data frame of lat and long coordinates.
Thanks for any help you can provide! If there's an easy explanation somewhere on this site or others that I missed, please point me in that direction! I couldn't find anything.
Cheers
For x-y coordinates that are in the same units (e.g. meters rather than degrees of latitude and degrees of longitude), you can use this function to get a data.frame of jump sizes and turning angles (in degrees).
getSteps <- function(x,y) {
d <- diff(complex(real = x, imaginary = y))
data.frame(size = Mod(d),
angle = c(NA, diff(Arg(d)) %% (2*pi)) * 360/(2*pi))
}
## Try it out
set.seed(1)
x <- rnorm(10)
y <- rnorm(10)
getSteps(x, y)
# size angle
# 1 1.3838360 NA
# 2 1.4356900 278.93771
# 3 2.9066189 101.98625
# 4 3.5714584 144.00231
# 5 1.6404354 114.73369
# 6 1.3082132 135.76778
# 7 0.9922699 74.09479
# 8 0.2036045 141.67541
# 9 0.9100189 337.43632
## A plot helps check that this works
plot(x, y, type = "n", asp = 1)
text(x, y, labels = 1:10)
You can do a transformation bewteen cartesian and polar this way:
polar2cart <- function(r, theta) {
data.frame(x = r * cos(theta), y = r * sin(theta))
}
cart2polar <- function(x, y) {
data.frame(r = sqrt(x^2 + y^2), theta = atan2(y, x))
}
Since it is fairly straight forward, you can write your own function. Matlab-like cart2pol function in R:
cart2pol <- function(x, y)
{
r <- sqrt(x^2 + y^2)
t <- atan(y/x)
c(r,t)
}
I used Josh O'Brien's code and got what appear to be reasonable jumps and angles—they match up pretty well to eyeballing the rough distance and heading between points. I then used a formula from his suggestions to create a function to turn the polar coordinates back to cartesian coordinates, and a for loop to apply the function to the data frame of all of the polar coordinates. The loops appear to work, and the outputs are in the correct units, but I don't believe the values that it's outputting are corresponding to my data. So either I did a miscalculation with my formula, or there's something else going on. More details below:
Here's the head of my lat long data:
> head(Tag1SSM[,3:4])
lon lat
1 130.7940 -2.647957
2 130.7873 -2.602994
3 130.7697 -2.565903
4 130.7579 -2.520757
5 130.6911 -2.704841
6 130.7301 -2.752182
When I plot the full dataset just as values, I get this plot:
which looks exactly the same as if I were to plot this using any spatial or mapping package in R.
I then used Josh's function to convert my data to polar coordinates:
x<-Tag1SSM$lon
y<-Tag1SSM$lat
getSteps <- function(x,y) {
d <- diff(complex(real = x, imaginary = y))
data.frame(size = Mod(d),
angle = c(NA, diff(Arg(d)) %% (2*pi)) * 360/(2*pi))
}
which produced the following polar coordinates appropriately:
> polcoords<-getSteps(x,y)
> head(polcoords)
size angle
1 0.04545627 NA
2 0.04103718 16.88852
3 0.04667590 349.38153
4 0.19581350 145.35439
5 0.06130271 59.37629
6 0.01619242 31.86359
Again, these look right to me, and correspond well to the actual angles and relative distances between points. So far so good.
Now I want to convert these back to cartesian coordinates and calculate a euclidian distance from the origin. These don't have to be in true lat/long, as I'm just comparing them amongst themselves. So I'm happy for the origin to be set as (0,0) and for distances to be calculated in reference x,y values instead of kilometers or something like that.
So, I used this function with Josh's help and a bit of web searching:
polar2cart<-function(x,y,size,angle){
#convert degrees to radians (dividing by 360/2*pi, or multiplying by pi/180)
angle=angle*pi/180
if(is.na(x)) {x=0} #this is for the purpose of the for loop below
if(is.na(y)) {y=0}
newx<-x+size*sin(angle) ##X #this is how you convert back to cartesian coordinates
newy<-y+size*cos(angle) ##Y
return(c("x"=newx,"y"=newy)) #output the new x and y coordinates
}
And then plugged it into this for loop:
u<-polcoords$size
v<-polcoords$angle
n<-162 #I want 162 new coordinates, starting from 0
N<-cbind(rep(NA,163),rep(NA,163)) #need to make 163 rows, though, for i+1 command below— first row will be NA
for(i in 1:n){
jump<-polar2cart(N[i,1],N[i,2],u[i+1],v[i+1]) #use polar2cart function above, jump from previous coordinate in N vector
N[i+1,1]<-jump[1] #N[1,] will be NA's which sets the starting point to 0,0—new coords are then calculated from each previous N entry
N[i+1,2]<-jump[2]
Dist<-sqrt((N[163,1]^2)+(N[163,2]^2))
}
And then I can take a look at N, with my new coordinates based on those jumps:
> N
[,1] [,2]
[1,] NA NA
[2,] 0.011921732 0.03926732
[3,] 0.003320851 0.08514394
[4,] 0.114640605 -0.07594871
[5,] 0.167393509 -0.04472125
[6,] 0.175941466 -0.03096891
This is where the problem is... the x,y coordinates from N get progressively larger—there's a bit of variation in there, but if you scroll down the list, y goes from 0.39 to 11.133, with very few backward steps to lower values. This isn't what my lat/long data do, and if I calculated the cart->pol and pol->cart properly, these new values from N should match my lat/long data, just in a different coordinate system. This is what the N values look like plotted:
Not the same at all... The last point in N is the farthest point from the origin, while in my lat/long data, the last point is actually quite close to the first point, and definitely not the farthest point away. I think the issue must be in my conversion from polar coordinates back to cartesian coordinates, but I'm not sure how to fix it...
Any help in solving this would be much appreciated!
Cheers
I think this code I wrote converts to polar coordinates:
# example data
x<-runif(30)
y<-runif(30)
# center example around 0
x<-x-mean(x)
y<-y-mean(y)
# function to convert to polar coordinates
topolar<-function(x,y){
# calculate angles
alphas<-atan(y/x)
# correct angles per quadrant
quad2<-which(x<0&y>0)
quad3<-which(x<0&y<0)
quad4<-which(x>0&y<0)
alphas[quad2]<-alphas[quad2]+pi
alphas[quad3]<-alphas[quad3]+pi
alphas[quad4]<-alphas[quad4]+2*pi
# calculate distances to 0,0
r<-sqrt(x^2+y^2)
# create output
polar<-data.frame(alphas=alphas,r=r)
}
# call function
polar_out<-topolar(x,y)
# get out angles
the_angles<-polar_out$alphas
Another option only in degree
pol2car = function(angle, dist){
co = dist*sin(angle)
ca = dist*cos(angle)
return(list(x=ca, y=co))
}
pol2car(angle = 45, dist = sqrt(2))
cart2sph {pracma} Transforms between cartesian, spherical, polar, and cylindrical coordinate systems in two and three dimensions.