如何将函数应用于增加数据框中的数据子集

Posted

技术标签:

【中文标题】如何将函数应用于增加数据框中的数据子集【英文标题】:How to apply a function to increasing subsets of data in a data frame 【发布时间】:2014-01-08 01:14:59 【问题描述】:

我希望将一组预先编写的函数应用于数据帧中逐渐增大的数据子集。在这个例子中,预先编写的函数计算 1)一系列数据点中每对连续位置之间的距离,2)一系列数据点的总距离(步骤 1 的总和),3)直线一系列数据点的开始和结束位置之间的距离和 4)直线距离(步骤 3)与总距离(步骤 2)之间的比率。我想知道如何将这些步骤(以及因此类似的功能)应用到数据框中不断增加的子组中。下面是一些示例数据和预先编写的函数。

示例数据:

> dput(df)
structure(list(latitude = c(52.640715, 52.940366, 53.267749, 
53.512608, 53.53215, 53.536443), longitude = c(3.305727, 3.103194, 
2.973257, 2.966621, 3.013587, 3.002674)), .Names = c("latitude", 
"longitude"), class = "data.frame", row.names = c(NA, -6L))

  Latitude Longitude
1 52.64072  3.305727
2 52.94037  3.103194
3 53.26775  2.973257
4 53.51261  2.966621
5 53.53215  3.013587
6 53.53644  3.002674

预写函数:

# Step 1: To calculate the distance between a pair of locations
pairdist = sapply(2:nrow(df), function(x) with(df, trackDistance(longitude[x-1], latitude[x-1], longitude[x], latitude[x], longlat=TRUE))) 
# Step 2: To sum the total distance between all locations
totdist = sum(pairdist)
# Step 3: To calculate the distance between the first and end location 
straight = trackDistance(df[1,2], df[1,1], df[nrow(df),2], df[nrow(df),1], longlat=TRUE)
# Step 4: To calculate the ratio between the straightline distance & total distance
distrat = straight/totdist

我想首先将这些函数应用于仅前两行(即第 1-2 行)的子组,然后应用于前三行(第 1-3 行)的子组,然后是四行……依此类推……直到我到达数据框的末尾(在示例中,这将是一个包含第 1-6 行的子组,但很高兴知道如何将其应用于任何数据框)。

期望的输出:

Subgroup  Totdist   Straight    Ratio
1         36.017     36.017     1.000                  
2         73.455     73.230     0.997
3        100.694     99.600     0.989
4        104.492    101.060     0.967
5        105.360    101.672     0.965

我曾尝试这样做但没有成功,目前这超出了我的能力范围。任何建议将不胜感激!

【问题讨论】:

【参考方案1】:

可以做很多优化。

trackDistance() 是矢量化的,所以你不需要申请。 要获得计算总距离的矢量化方式,请使用cumsum() 您只需要计算成对距离一次。每次查看不同的子集时都重新计算是浪费资源。因此,在构建函数时,请尝试考虑完整的数据框架。

要在一个输出所需数据帧的函数中获取所有内容,您可以按照以下方式进行操作:

myFun <- function(x)
  # This is just to make typing easier in the rest of the function
  lat <- x[["Latitude"]]
  lon <- x[["Longitude"]]
  nr <- nrow(x)

  pairdist <-trackDistance(lon[-nr],lat[-nr],
                           lon[-1],lat[-1],
                           longlat=TRUE)

  totdist <- cumsum(pairdist)

  straight <- trackDistance(rep(lon[1],nr-1),
                            rep(lat[1],nr-1),
                            lon[-1],lat[-1],
                            longlat=TRUE)

  ratio <- straight/totdist
  data.frame(totdist,straight,ratio)


概念证明:

> myFun(df)
    totdist  straight     ratio
1  36.01777  36.01777 1.0000000
2  73.45542  73.22986 0.9969293
3 100.69421  99.60013 0.9891346
4 104.49261 101.06023 0.9671519
5 105.35956 101.67203 0.9650005

请注意,您可以添加额外的参数来定义纬度和经度列。并注意您的大小写,在您的问题中,您在数据框中使用纬度,但在代码中使用纬度(小 l)。

【讨论】:

@Joris:谢谢你的解决方案。太棒了!正是我想做的。非常感谢,圣诞快乐!

以上是关于如何将函数应用于增加数据框中的数据子集的主要内容,如果未能解决你的问题,请参考以下文章

如何根据不同 R 生态系统中的另一个向量重写代码,将函数应用于行子集?

根据时间频率将特定函数应用于数据帧的某个子集

将函数应用于数据框中的每一列,观察每一列现有的数据类型

将函数应用于两列并将输出映射到新列[重复]

将 func 应用于 R 数据框中的所有元素(按列)[重复]

将邮政编码 API 调用应用于数据框中的每一行