List outcomes in loops- gmapsdistance - r

I am trying to use the R package gmapsdistance to calculate the road distance and travel time between two sets of co-ordinates. I have created the following loop as I have 2524 routes to calculate.
for(i in 1:2524) {
df$Distance_Time[i] <- as.data.frame(gmapsdistance
(origin = c(df$OriginCo[i]),
destination = c(df$DestinationCo[i]),
combinations = "pairwise",
mode = "driving",
shape = "long",
set.api.key("MY_API_KEY")))
}
An example of my df is as follow;
OriginCo : chr "-39.9+174.99", "-40.27+175.55", "-39.66+176.77"...
DestinationCo : chr "-40.27+175.55", "-39.9+174.99", "-40.27+175.55"...
Distance_Time :
However, because the output of gmapdistance is a list, the new column in the df (Distance_time) only shows the travel time for each set of co-ordinates.
If I run the code on the first set of co-ordinates, instead of a loop, I get $time, $distance and $status.
How can I make another column to show distance and status or have these two variables listed along with the $time?
Many thank in advance

Related

How can I calculate ETP (Hargreaves) from a NetCDF using xarray.apply_ufunc() with GroupBy

The following illustrates how I tried computing the ETP on a netCDF using xarray_ufunc.
# stack the lat and lon dimensions into a new dimension named point, so at each lat/lon
# we'll have a time series for the geospatial point, and group by these points
tmin_da = ds.tmin.stack(point=('lat', 'lon')).groupby('point')
tmax_da = ds.tmax.stack(point=('lat', 'lon')).groupby('point')
tmean_da = ds.tmean.stack(point=('lat', 'lon')).groupby('point')
# apply the SPI function to the data array
ds = xr.apply_ufunc(eto.eto_hargreaves, tmin_da, tmax_da, tmean_da, latitude_degrees = np.linspace(23.125 , 49.125, 14))
Code error
The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Any suggestions on how the input data should be or another easy method?

How to input multiple departure dates and times in gmapsdistance R package?

I am using the R package, gmapsdistance, to extract Google distance matrix.
My codes are:
gdm <- gmapsdistance(origin = origin_vector,
destination = destination_vector,
combinations = "pairwise",
mode = "driving",
shape = "long",
dep_date = date_vector,
dep_time = time_vector)
The Google API key was also set. The code works until the parameters for dep_date and dep_time. I believe it is because the parameters do not accept vectors. Two errors appear:
1: XML declaration allowed only at the start of the document.
2: Extra content at the end of the document.
In my dataset, each row is a data point with a unique origin, destination, departure date, and departure time. I require the Google distance/time for each row and there are thousands of them. There is no need for me to compare across rows. How may I do this?
Appreciate any help!

How to group repeating sequences of numbers using R

The simplest description of what I am trying to do is that I have a column in a data.frame like 1,2,3,..., n, 1,2,3,...n,.... and I want group the first 1...n as 1 the second 1...n as 2 and so on.
The full context is; I am using the R spcosa package to do equal area stratification composite sampling on parcels of land. I start with a shape file from a GIS that contains a number of polygons (land parcels). The end result I want is a GIS file with each of the strata and sample locations in a GIS file format with each stratum and sample location labeled by land parcel, stratum and sample id. So far I can do all this except one bit which is identifying the stratum that the samples belongs too and including it in the sample label. The sample label needs to look like "parcel#-strata#-composite# (where # is the number). In practice I don't need this actual label but as separate attributes in GIS file.
The basic work flow is a follows
For each individual polygon using spcosa::stratify I divide it into a number of equal area strata like
strata.CSEA <- stratify(poly[i,], nStrata = n, nTry = 1, equalArea = TRUE, nGridCells = x)
Note spcosa::stratify generates a CompactStratificationEqualArea object. I cocerce this to a SpatialPixelData then use rasterToPolygon to be able to output it as a GIS file.
I then generate the sample locations as follows:
samples.SPRC <- spsample(strata.CSEA, n = n, type = "composite")
spcosa::spsample creates a SamplingPatternRandomComposite object. I coerce this to a SpatialPointsDataFrame
samples.SPDF <- as(samples.SPRC, "SpatialPointsDataFrame")
and add two columns to the #data slot
samples.SPDF#data$Strata <- "this is the bit I can't do yet"
samples.SPDF#data$CEA <- poly[i,]$name
I can then write samples.SPDF as a GIS file ( ie writeOGE) with all the wanted attributes.
As above the part I can't sort out is how the sample ids relate to the strata ids. The sample points are a vector like 1,2,3...n, 1,2,3...n,.... How do I extract which sample goes with which strata? As actual strata number are arbitrary, I can just group ( as per my simple question above) but ideally I would like to use the numbering of the actual strata so everything lines up.
To give any contributors access to a hands on example I copy below the code from the spcosa documentation slightly modified to generate the correct objects.
# Note: the example below requires the 'rgdal'-package You may consider the 'maptools'-package as an alternative
if (require(rgdal)) {
# read a vector representation of the `Farmsum' field
shpFarmsum <- readOGR(
dsn = system.file("maps", package = "spcosa"),
layer = "farmsum"
)
# stratify `Farmsum' into 50 strata
# NB: increase argument 'nTry' to get better results
set.seed(314)
myStratification <- stratify(shpFarmsum, nStrata = 50, nTry = 1, equalArea = TRUE)
# sample two sampling units per stratum
mySamplingPattern <- spsample(myStratification, n = 2 type = "composite")
# plot the resulting sampling pattern on
# top of the stratification
plot(myStratification, mySamplingPattern)
}
Maybe order() function can help you
n <- 10
dat <- data.frame(col1 = rep(1:n, 2), col2 = rnorm(2*n))
head(dat)
dat[order(dat$col1), ]
I did not get where the "ID" (1,2,3...n) is to be found; so let's assume you have your SpatialPolygonsDataFrame called shpFarmsum with a attribute data column "ID". You can access this column via shpFarmsum$ID. Therefore, if you want to create individual subsets for each ID this is one way to go:
for (i in unique(shpFarmsum$ID)) {
tempSubset shpFarmsum[shpFarmsum$ID == i,]
writeOGR(tempSubset, ".", paste0("subset_", i), driver = "ESRI Shapefile")
}
I added the line writeOGR(... so all subsets are written to your working direktory. However, you can change this line or add further analysis into the for-loop.
How it works
unique(shpFarmsum$ID) extracts all occuring IDs (compareable to your 1,2,3...n).
In each repetition of the for loop, another value of this IDs will be used to create a subset of the whole SpatialPolygonsDataFrame, which you can use for further analysis.

How to calculate distance between multiple lon lat vectors using R

My data set is as below-
a
Location loc.Lon loc.Lat Pincode pin.lon pin.lat
SPM 79.94533 12.97025 "602105" 79.95285 12.96752
SPM 79.94533 12.97025 "602106" 79.88568 12.91943
I want to calculate the distance between (loc.Lon, loc.Lat) and (pin.lon, pin.lat) for both the pincodes using the package ggmap.
when I run the below code, I get the desired result -
mapdist(c(a$loc.Lon[2], a$loc.Lat[2]), c(a$pin.lon[2],a$pin.lat[2]), mode = "driving")
but when I run the below query for the entire data set a, I get an error -
a$dist = mapdist(c(a$loc.Lon, a$loc.Lat), c(a$pin.lon,a$pin.lat), mode = "driving")
error I get is -
Error: is.character(from) is not TRUE
Please help me getting this sorted.
mapdist accepts vectors for the from and to arguments, so you can convert them and apply this function to each line of you data set.
Supposing you want the km distance:
get_km_from_mapdist <- function(i) {
mapdist(as.numeric(a[i, c('loc.Lon','loc.Lat')]),
as.numeric(a[i, c('pin.lon','pin.lat')]),
mode='driving')$km
}
a$dists = sapply(1:nrow(a), get_km_from_mapdist)
Cast the coordinates as strings with as.character() and paste0() them when calling mapdist directly onto your data.
a$dist_km <- mapdist(from = paste0(as.character(a$loc.Lat),",",as.character(a$loc.Lon)),
to = paste0(as.character(a$pin.Lat),", ",as.character(a$pin.Lon)))[,c('km')]

Creating SpatialLinesDataFrame from SpatialLines object and basic df

Using leaflet, I'm trying to plot some lines and set their color based on a 'speed' variable. My data start at an encoded polyline level (i.e. a series of lat/long points, encoded as an alphanumeric string) with a single speed value for each EPL.
I'm able to decode the polylines to get lat/long series of (thanks to Max, here) and I'm able to create segments from those series of points and format them as a SpatialLines object (thanks to Kyle Walker, here).
My problem: I can plot the lines properly using leaflet, but I can't join the SpatialLines object to the base data to create a SpatialLinesDataFrame, and so I can't code the line color based on the speed var. I suspect the issue is that the IDs I'm assigning SL segments aren't matching to those present in the base df.
The objects I've tried to join, with SpatialLinesDataFrame():
"sl_object", a SpatialLines object with ~140 observations, one for each segment; I'm using Kyle's code, linked above, with one key change - instead of creating an arbitrary iterative ID value for each segment, I'm pulling the associated ID from my base data. (Or at least I'm trying to.) So, I've replaced:
id <- paste0("line", as.character(p))
with
lguy <- data.frame(paths[[p]][1])
id <- unique(lguy[,1])
"speed_object", a df with ~140 observations of a single speed var and row.names set to the same id var that I thought I created in the SL object above. (The number of observations will never exceed but may be smaller than the number of segments in the SL object.)
My joining code:
splndf <- SpatialLinesDataFrame(sl = sl_object, data = speed_object)
And the result:
row.names of data and Lines IDs do not match
Thanks, all. I'm posting this in part because I've seen some similar questions - including some referring specifically to changing the ID output of Kyle's great tool - and haven't been able to find a good answer.
EDIT: Including data samples.
From sl_obj, a single segment:
print(sl_obj)
Slot "ID":
[1] "4763655"
[[151]]
An object of class "Lines"
Slot "Lines":
[[1]]
An object of class "Line"
Slot "coords":
lon lat
1955 -74.05228 40.60397
1956 -74.05021 40.60465
1957 -74.04182 40.60737
1958 -74.03997 40.60795
1959 -74.03919 40.60821
And the corresponding record from speed_obj:
row.names speed
... ...
4763657 44.74
4763655 34.8 # this one matches the ID above
4616250 57.79
... ...
To get rid of this error message, either make the row.names of data and Lines IDs match by preparing sl_object and/or speed_object, or, in case you are certain that they should be matched in the order they appear, use
splndf <- SpatialLinesDataFrame(sl = sl_object, data = speed_object, match.ID = FALSE)
This is documented in ?SpatialLinesDataFrame.
All right, I figured it out. The error wasn't liking the fact that my speed_obj wasn't the same length as my sl_obj, as mentioned here. ("data =
object of class data.frame; the number of rows in data should equal the number of Lines elements in sl)
Resolution: used a quick loop to pull out all of the unique lines IDs, then performed a left join against that list of uniques to create an exhaustive speed_obj (with NAs, which seem to be OK).
ids <- data.frame()
for (i in (1:length(sl_obj))) {
id <- data.frame(sl_obj#lines[[i]]#ID)
ids <- rbind(ids, id)
}
colnames(ids)[1] <- "linkId"
speed_full <- join(ids, speed_obj)
speed_full_short <- data.frame(speed_obj[,c(-1)])
row.names(speed_full_short) <- speed_full$linkId
splndf <- SpatialLinesDataFrame(sl_obj, data = speed_full_short, match.ID = T)
Works fine now!
I may have deciphered the issue.
When I am pulling in my spatial lines data and I check the class it reads as
"Spatial Lines Data Frame" even though I know it's a simple linear shapefile, I'm using readOGR to bring the data in and I believe this is where the conversion is occurring. With that in mind the speed assignment is relatively easy.
sl_object$speed <- speed_object[ match( sl_object$ID , row.names( speed_object ) ) , "speed" ]
This should do the trick, as I'm willing to bet your class(sl_object) is "Spatial Lines Data Frame".
EDIT: I had received the same error as OP, driving me to check class()
I am under the impression that the error that was populated for you is because you were trying to coerce a data frame into a data frame and R wasn't a fan of that.

Resources