这个问题在这里已有答案:
我创建了一个计算大量生物统计数据的函数,例如物种范围边缘 . 这是该函数的简化版本:
range_stats <- function(rangedf, lat, lon, weighting, na.rm=T){
cent_lat <- weighted.mean(x=rangedf[,lat], w=rangedf[,weighting], na.rm=T)
cent_lon <- weighted.mean(x=rangedf[,lon], w=rangedf[,weighting], na.rm=T)
out <- data.frame(cent_lat, cent_lon)
return(out)
}
我想将它应用于一个大型数据框,其中每一行都是一个物种的观察 . 因此,我希望函数按指定的一组列对行进行分组,然后为每个组计算这些统计信息 . 这是一个测试数据帧:
LATITUDE <- c(27.91977, 21.29066, 26.06340, 28.38918, 25.97517, 27.96313)
LONGITUDE <- c(-175.8617, -157.8645, -173.9593, -178.3571, -173.9679, -175.7837)
BIOMASS <- c(4.3540488, 0.2406332, 0.2406332, 2.1419699, 0.3451426, 1.0946017)
SPECIES <- c('Abudefduf abdominalis','Abudefduf abdominalis','Abudefduf abdominalis','Chaetodon lunulatus','Chaetodon lunulatus','Chaetodon lunulatus')
YEAR <- c('2005', '2005', '2014', '2009', '2009', '2015')
testdf <- data.table(LATITUDE, LONGITUDE, BIOMASS, SPECIES, YEAR)
我想将此函数应用于物种和年份的每个独特组合,以计算汇总统计数据,即,以下内容:
testresult <- testdf %>%
group_by(SPECIES, YEAR) %>%
range_stats(lat="LATITUDE",lon="LONGITUDE",weighting="BIOMASS",na.rm=T)
但是,上面的代码不起作用(我得到 (list) object cannot be coerced to type 'double'
错误),我不知道如何解决问题 .
2 回答
由于您添加了
dplyr
和purrr
的标记,我假设您对tidyverse
解决方案感兴趣 . 所以下面我将演示一个基于tidyverse
的解决方案 .首先,你的
range_stats
是有问题的 . 这就是您收到错误消息的原因 .weighted.mean
期待x
和w
参数的向量 . 但是,如果rangedf
是tibble
,则tibble
的子集方式(例如rangedf[,lat]
)仍将返回单列tibble
. 更好的方法是使用dplyr
包中的pull
.接下来,您创建数据框的方式是正常的,但
data.table
来自data.table
包,您将创建data.table
,而不是tibble
. 我以为你想使用tidyverse
的方法,所以我将data.table
更改为data_frame
,如下所示 .现在,您说要将
range_stats
函数应用于SPECIES
和YEAR
的每个组合 . 一种方法是将数据帧拆分为数据帧列表,并使用lapply
族函数 . 但是在这里我想向您展示如何使用map
族函数来实现此任务,因为map
来自purrr
包,它是tidyverse
的一部分 .我们可以首先根据
SPECIES
和YEAR
创建组索引 .如您所见,
Group
是显示索引号的新列 . 现在我们可以基于Group
拆分数据框,然后使用map_dfr
来应用range_stats
函数 .请注意,
map_dfr
可以自动将数据帧的输出列表绑定到单个数据帧 ..id = "Group"
表示我们要根据list元素的名称创建一个名为Group
的列 .我将这个过程分为两个步骤,但当然它们可以在一个管道中完成,如下所示 .
如果你愿意,
testresult
可以使用left_join
与testdf
合并,但我会在此停止,因为testresult
可能已经是您想要的所需输出 . 我希望这有帮助 .从根本上说,主要问题涉及
weighted.mean()
,您传递的是数据框对象,而不是可以强制转换为double的矢量 . 要修复方法,只需更改:双括号:
调整方法:
至于整体分组计算,请原谅我绕过你使用的
dplyr
和data.table
,并考虑基础R未充分利用但有用的方法,by()
.当前设置的挑战是range_stats方法的输出return是两列的data.frame,而dplyr的
group_by()
期望一个聚合向量操作 . 但是,by
将数据框对象(按因子切片)传递到已定义的函数中,以返回data.frames列表,然后您可以rbind
获取最终的一个数据帧: