Reputation: 23
Given a list of xy coordinates how can one populate a rectangular xy grid with standard incremental changes of 0.5 with where a given coordinate pair occurs?
For example, say we have the following coordinate pairs:
pts <- data.frame(X = c(1.9,2.4,1.1), Y = c(4.5,1.2,3.2))
And empty grid such as:
gridX = seq(0,2.5,by=0.5)
gridY = seq(0,5,by=0.5)
How to create a result which indicates whether a grid section contains a coordinate pair such that:
result
0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5
1 0.0 0 0 0 0 0 0 0 0 0 0 0
2 0.5 0 0 0 0 0 0 0 0 0 0 0
3 1.0 0 0 0 0 0 0 0 0 0 0 0
4 1.5 0 0 0 0 0 0 0 1 0 1 0
5 2.0 0 0 0 0 0 0 0 0 0 0 0
6 2.5 0 0 0 1 0 0 0 0 0 0 0
A somewhat similar question is posed here (using Python): How to check if a coordinate pair (lat,lon) exists in a coordinate grid?. However I need to figure out how to this for multiple coordinate pairs, including instances where more than one coordinate pair might fall within the same grid section, that grid section would still be 1.
Upvotes: 2
Views: 261
Reputation: 1159
You can build upon the following.
pts <- data.frame(X = c(1.9,2.4,1.1), Y = c(4.5,1.2,3.2))
gridX = seq(0, 2.5, by=0.5)
gridY = seq(0, 5, by=0.5)
grid.matrix <- matrix(0, nrow=length(gridY), ncol=length(gridX))
grid <- data.frame(
grid.matrix,
row.names=gridY)
colnames(grid) <- gridX
The only thing left now is to find the correct row and column. This can be done with an iflese
, for example.
EDIT
A better way to do it is to use match
and aggregate
. The full code listening looks as follows.
pts <- data.frame(X = c(1.9,2.4,1.1), Y = c(4.5,1.2,3.2))
gridX = seq(0, 2.5, by=0.5)
gridY = seq(0, 5, by=0.5)
grid.matrix <- matrix(0, nrow=length(gridY), ncol=length(gridX))
grid <- data.frame(
grid.matrix,
row.names=gridY)
colnames(grid) <- gridX
pts$X.in.grid <- round(pts$X*2)/2
pts$Y.in.grid <- round(pts$Y*2)/2
pts$X.idx.in.grid <- match( pts$X.in.grid , colnames(grid) )
pts$Y.idx.in.grid <- match( pts$Y.in.grid , row.names(grid))
df.update <- aggregate(
X.idx.in.grid + Y.idx.in.grid ~ X.idx.in.grid + Y.idx.in.grid ,
pts, length )
colnames(df.update)[3] <- "value"
for (index in 1:nrow(df.update)) {
grid[ df.update$Y.idx.in.grid[index], df.update$X.idx.in.grid[index] ] <- df.update$value[index]
}
which gives you.
structure(list(`0` = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), `0.5` = c(0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0), `1` = c(0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0), `1.5` = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), `2` = c(0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0), `2.5` = c(0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0)), row.names = c("0", "0.5", "1", "1.5", "2", "2.5",
"3", "3.5", "4", "4.5", "5"), class = "data.frame")
Upvotes: 0
Reputation: 16978
Since your grid uses a step width of 0.5
you could use
> floor(pts*2)/2
X Y
1 1.5 4.5
2 2.0 1.0
3 1.0 3.0
to get the points on your grid.
Depending on your rounding logic, you could replace floor
by
> ceiling(pts*2)/2
X Y
1 2.0 4.5
2 2.5 1.5
3 1.5 3.5
or simply by rounding
> round(pts*2)/2
X Y
1 2.0 4.5
2 2.5 1.0
3 1.0 3.0
Adding the points to your grid depends on the data structure your grid is stored in.
For example: Your grid is stored in a matrix with named rows and columns
grid <- matrix(0, ncol=length(gridX), nrow=length(gridY))
rownames(grid) <- gridX
colnames(grid) <- gridY
and your new points are given by
new_pts <- round(pts*2)/2
In this case retrieve your desired matrix by
grid[as.character(new_pts$X), as.character(new_pts$Y)] <- diag(1,nrow(new_pts))
That's not very sophisticated, but it works.
Upvotes: 1