简体   繁体   English

将用户定义的函数应用于特定的数据框列

[英]Apply User-Defined Function to Specific Dataframe Columns

I have seen the question here R apply user define function on data frame columns but mine is a little different... 我在这里看到的问题是R在数据框列上应用了用户定义函数,但是我的有点不同...

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 . 然后,我有一个方法getDistance(lat1, lng1, lat2, lng2) ,我想将计算结果返回到我的数据帧中名为distance的新列中。

Update 更新

> 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: 例如,你可以使用distHaversine功能从geosphere包做计算在一个镜头:

# 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. 如果要使用apply系列中的函数,则可能会遍历数据框的行,一次计算一次距离。 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. 速度降低100倍的原因是,如果一次执行一行距离计算,则无法利用向量化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM