我创建了一个函数,可以计算许多生物统计信息,例如物种范围边缘。这是该函数的简化版本:
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)
}
Run Code Online (Sandbox Code Playgroud)
我想将其应用于大型数据框,其中每一行都是一个物种的观察结果。这样,我希望函数按一组指定的列对行进行分组,然后为每个组计算这些统计信息。这是一个测试数据帧:
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)
Run Code Online (Sandbox Code Playgroud)
我想将此功能应用于物种和年份的每个唯一组合以计算汇总统计信息,即以下内容:
testresult <- testdf %>%
group_by(SPECIES, YEAR) %>%
range_stats(lat="LATITUDE",lon="LONGITUDE",weighting="BIOMASS",na.rm=T)
Run Code Online (Sandbox Code Playgroud)
但是,上面的代码不起作用(出现(list) object cannot be coerced to type 'double'错误),并且我不确定如何解决该问题。
由于您添加了dplyrand标签purrr,我假设您对tidyverse解决方案感兴趣。所以下面我将演示一个基于tidyverse.
首先,你range_stats的问题。这就是您收到错误消息的原因。在weighted.mean期待了两个向量x和w论证。但是,如果rangedf是 a tibble,则您对 进行子集化的方式tibble,例如rangedf[,lat]仍将返回一列tibble。更好的方法是pull从dplyr包中使用。
library(tidyverse)
range_stats <- function(rangedf, lat, lon, weighting, na.rm=T){
cent_lat <- weighted.mean(x = rangedf %>% pull(lat),
w = rangedf %>% pull(weighting), na.rm=T)
cent_lon <- weighted.mean(x = rangedf %>% pull(lon),
w = rangedf %>% pull(weighting), na.rm=T)
out <- data.frame(cent_lat, cent_lon)
return(out)
}
Run Code Online (Sandbox Code Playgroud)
接下来,您创建数据框的方式是可以的,但是data.table来自data.table包,您将创建一个data.table. 而不是tibble. 我想你想使用的方法tidyverse,所以我换data.table到data_frame如下。
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_frame(LATITUDE, LONGITUDE, BIOMASS, SPECIES, YEAR)
Run Code Online (Sandbox Code Playgroud)
现在,你说你想要的应用range_stats功能的每个组合SPECIES和YEAR。一种方法是将数据框拆分为数据框列表,并使用lapply族函数。但在这里我想向你展示如何使用map家庭功能来实现这一任务,map从purrr包装,这是一部分tidyverse。
我们可以首先创建一个基于SPECIES和的组索引YEAR。
testdf2 <- testdf %>%
mutate(Group = group_indices(., SPECIES, YEAR))
testdf2
# A tibble: 6 x 6
LATITUDE LONGITUDE BIOMASS SPECIES YEAR Group
<dbl> <dbl> <dbl> <chr> <chr> <int>
1 27.91977 -175.8617 4.3540488 Abudefduf abdominalis 2005 1
2 21.29066 -157.8645 0.2406332 Abudefduf abdominalis 2005 1
3 26.06340 -173.9593 0.2406332 Abudefduf abdominalis 2014 2
4 28.38918 -178.3571 2.1419699 Chaetodon lunulatus 2009 3
5 25.97517 -173.9679 0.3451426 Chaetodon lunulatus 2009 3
6 27.96313 -175.7837 1.0946017 Chaetodon lunulatus 2015 4
Run Code Online (Sandbox Code Playgroud)
如您所见,Group是一个显示索引号的新列。现在我们可以根据 来分割数据框Group,然后使用map_dfr来应用range_stats函数。
testresult <- testdf2 %>%
split(.$Group) %>%
map_dfr(range_stats, lat = "LATITUDE",lon = "LONGITUDE",
weighting = "BIOMASS", na.rm = TRUE, .id = "Group")
testresult
Group cent_lat cent_lon
1 1 27.57259 -174.9191
2 2 26.06340 -173.9593
3 3 28.05418 -177.7480
4 4 27.96313 -175.7837
Run Code Online (Sandbox Code Playgroud)
请注意,map_dfr可以自动将数据帧的输出列表绑定到单个数据帧。.id = "Group"意味着我们要创建一个Group基于列表元素名称的列。
我将这个过程分为两个步骤,但当然它们可以都在一个管道中,如下所示。
testresult <- testdf %>%
mutate(Group = group_indices(., SPECIES, YEAR)) %>%
split(.$Group) %>%
map_dfr(range_stats, lat = "LATITUDE",lon = "LONGITUDE",
weighting = "BIOMASS", na.rm = TRUE, .id = "Group")
Run Code Online (Sandbox Code Playgroud)
如果你愿意,testresult可以与testdfusing合并left_join,但我会在这里停下来,因为testresult可能已经是你想要的输出了。我希望这有帮助。
| 归档时间: |
|
| 查看次数: |
2345 次 |
| 最近记录: |