I have seen the question here R apply user define function on data frame columns but mine is a little different...
I would like to pass specific columns of my dataframe to a function, then return the result of that function to a new column of my dataframe.
Basically, I have a dataframe like this:
df.latitude1
df.longitude1
df.latitude2
df.longitude2
Then I have a method getDistance(lat1, lng1, lat2, lng2)
and I would like to return the result of that computation into a new column in my dataframe called distance
.
> asn$geoDistance <- distHaversine(asn[,c("homeLocationGeoLat", "homeLocationGeoLng")], dat[,c("hostLocationGeoLat", "hostLocationGeoLng")])
Error in .pointsToMatrix(p1) : latitude < -90
> asn$homeLocationGeoLat[asn$homeLocationGeoLat < -90]
[1] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[40] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[79] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[118] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[157] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[196] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[235] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[274] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[313] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[352] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[391] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[430] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[469] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[508] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[547] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
> asn$hostLocationGeoLat[asn$hostLocationGeoLat < -90]
[1] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[40] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[79] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[118] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[157] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[196] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[235] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[274] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[313] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[352] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[391] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[430] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[469] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[508] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[547] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[586] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[625] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[664] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[703] NA NA NA NA NA NA NA NA NA
> newDf <- asn[, c('durationDays', 'homeLocationGeoLat', 'homeLocationGeoLng', 'hostLocationGeoLat', 'hostLocationGeoLng')]
> dput(head(newDf))
structure(list(durationDays = c(0, 0, 180, 0, 365, 0), homeLocationGeoLat = c(-23.5489433,
1.2800945, 12.9715987, 25.7889689, 49.3063689, 25.271139), homeLocationGeoLng = c(-46.6388182,
103.8509491, 77.5945627, -80.2264393, 8.6427693, 55.307485),
hostLocationGeoLat = c(37.4418834, 49.2774456, 52.3905689,
49.3063689, 53.3498053, 37.4418834), hostLocationGeoLng = c(-122.1430195,
7.1118995, 13.0644729, 8.6427693, -6.2603097, -122.1430195
)), .Names = c("durationDays", "homeLocationGeoLat", "homeLocationGeoLng",
"hostLocationGeoLat", "hostLocationGeoLng"), row.names = c(NA,
6L), class = "data.frame")
Your best bet is probably to use a vectorized function and compute the distances for all pairs of points at the same time. For instance, you could use the distHaversine
function from the geosphere
package to do the calculation in one shot:
# 10000 points
set.seed(144)
dat <- data.frame(lat1=runif(10000, 10, 20), lng1=runif(10000, 10, 20),
lat2=runif(10000, 10, 20), lng2=runif(10000, 10, 20))
# Get all distances
library(geosphere)
dat$distance <- distHaversine(dat[,c("lng1", "lat1")], dat[,c("lng2", "lat2")])
head(dat$distance)
# [1] 293912.3 332583.2 870767.8 167362.9 371920.6 659368.1
If you were going to use a function from the apply
family, you would probably loop through the rows of your data frame, computing the distances one at a time. While this will give the same answer, it will be much slower:
all.equal(distHaversine(dat[,c("lng1", "lat1")], dat[,c("lng2", "lat2")]),
apply(dat, 1, function(x) distHaversine(x[c("lng1", "lat1")], x[c("lng2", "lat2")])))
# [1] TRUE
system.time(distHaversine(dat[,c("lng1", "lat1")], dat[,c("lng2", "lat2")]))
# user system elapsed
# 0.005 0.001 0.008
system.time(apply(dat, 1, function(x) distHaversine(x[c("lng1", "lat1")], x[c("lng2", "lat2")])))
# user system elapsed
# 0.887 0.007 0.895
The reason for the 100x slowdown is that you can't take advantage of vectorization if you perform the distance computation one row at a time.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.