【问题标题】:Applying an iterative/non-aggregating function to multiple subsets of data in R将迭代/非聚合函数应用于 R 中的多个数据子集
【发布时间】:2019-11-17 00:04:39
【问题描述】:

我正在尝试运行一个需要在数据集的子集中建立索引的函数,但在如何设置该函数时遇到了麻烦。具体来说,我正在尝试计算给定年份沿特定样带的距离,因此对于每个子集,我需要 1)确定样带中的一个端点,以及 2)计算该端点沿线的欧几里得距离子集中的其他位置。

如果我将整个数据集视为单个样带,该函数似乎可以工作:

df <- data.frame(
  Transect = c(rep(1,4),rep(2,4)),
  YYYY = c(2015,2015,2016,2016,2015,2015,2016,2016),
  X = seq(2,16, by = 2),
  Y = c(1,2,3,5,6,13,22,31))

df$dist <- NA

f <- function(X, Y) {
  xs_start <- match(min(X), X)  #assumes no transects are perfectly N-S
  for (n in 1:length(X)){
    dist[n] <- (((Y[n]-Y[xs_start])^2)+((X[n]-X[xs_start])^2))^.5
  }
  return(dist)
}
attach(df)
f(X, Y)
detach(df)

但是,在数据子集上运行它给我带来了麻烦。我可以使用data.table 和dplyr 成功地对数据帧进行子集化,但是在尝试在子集上运行函数时遇到了不同的问题。我发现的大多数文档都集中在聚合数据子集的方法上(有时将汇总数字加入到整个组中)。

使用data.table,我可以正确计算第一个样带,但其余部分会产生 NA,然后将整个结果向量加入每个组,而不仅仅是来自该子集的结果。

library(data.table)
dt <- data.table(df)
dt[,f(X, Y), by = .(Transect, YYYY)]

使用dplyr 也是一种选择,但同样,我不确定如何使其适用于不聚合数据的函数。

library(dplyr)
df  %>%
  group_by(Transect, YYYY) %>%
  mutate(dist = f(X, Y))

以上代码生成Error: Column 'dist' must be length 2 (the group size) or one, not 8。

有什么想法吗?提前致谢!

【问题讨论】:

  • 即使没有分组数据,您的函数也会出错
  • @akrun 即使在重新启动我的 R 会话并清除环境之后,当我复制并粘贴第一块代码时,该函数也会为我生成一个向量——你遇到了什么错误?
  • 我收到 with(df, f(X, Y)) Error in dist[n] &lt;- (((Y[n] - Y[xs_start])^2) + ((X[n] - X[xs_start])^2))^0.5 : object of type 'closure' is not subsettable 我没有收到 attach 因为它会产生问题
  • @akrun 我正在使用 attach 来尝试复制 dplyr/data.table 中将要发生的事情的语法,所以我不想使用“df$”——现在我将回顾那些似乎已经延续到我进行子集化时的代码。如果我将函数更改为引用整个数据框并使用 df$X 等为所有内容编制索引,它就会运行。这似乎也会使子集中部分的工作复杂化......
  • f

标签: r function dplyr data.table


【解决方案1】:

要添加一个列 dist 来计算从端点位置(最小 X 坐标)到每个样带年组中所有其他位置的欧几里得距离,您可以这样做:

## data
df <- data.frame(
    Transect = c(rep(1,4),rep(2,4)),
    YYYY = c(2015,2015,2016,2016,2015,2015,2016,2016),
    X = seq(2,16, by = 2),
    Y = c(1,2,3,5,6,13,22,31))

## with dplyr
library(dplyr)

df %>%
    group_by(Transect, YYYY) %>%
    mutate(dist = sqrt((Y - Y[which.min(X)])^2 + (X - min(X))^2)) %>%
    ungroup()
#> # A tibble: 8 x 5
#>   Transect  YYYY     X     Y  dist
#>      <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1        1  2015     2     1  0   
#> 2        1  2015     4     2  2.24
#> 3        1  2016     6     3  0   
#> 4        1  2016     8     5  2.83
#> 5        2  2015    10     6  0   
#> 6        2  2015    12    13  7.28
#> 7        2  2016    14    22  0   
#> 8        2  2016    16    31  9.22

## with data.table
library(data.table)

setDT(df)[, dist := sqrt((Y - Y[which.min(X)])^2 + (X - min(X))^2), by = c("Transect", "YYYY")][]
#>    Transect YYYY  X  Y     dist
#> 1:        1 2015  2  1 0.000000
#> 2:        1 2015  4  2 2.236068
#> 3:        1 2016  6  3 0.000000
#> 4:        1 2016  8  5 2.828427
#> 5:        2 2015 10  6 0.000000
#> 6:        2 2015 12 13 7.280110
#> 7:        2 2016 14 22 0.000000
#> 8:        2 2016 16 31 9.219544

【讨论】:

    猜你喜欢
    • 2022-01-17
    • 2020-03-22
    • 2020-02-17
    • 2020-10-13
    • 2018-02-22
    • 1970-01-01
    • 2019-03-27
    • 2014-11-10
    • 1970-01-01
    相关资源
    最近更新 更多