由于您添加了dplyr
和purrr
的标签,我假设您对tidyverse
解决方案感兴趣。所以下面我将演示一个基于tidyverse
的解决方案。
首先,您的range_stats
有问题。这就是你收到错误信息的原因。 weighted.mean
正在等待x
和w
参数的向量。但是,如果rangedf
是tibble
,则子集tibble
的方式(例如rangedf[,lat]
)仍将返回一列tibble
。更好的方法是使用dplyr
软件包中的pull
。
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)
}
接下来,我们创建了数据帧的方式是确定的,但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)
,你说你想要的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
正如您所看到的,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
注意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")
如果你想,testresult
可以使用left_join
testdf
合并,但我会在这里停止为testresult
可能已经你想所需的输出。我希望这有帮助。
完美解决方案,谢谢!我实现了它,除了mutate(group = group_indices(。,SPECIES,YEAR))外,我使用了一个有意义的列名,以便输出df中的标识符有意义:mutate(GROUPID = paste(YEAR,种))'。 – AFH
@AFH创建有意义的组名或ID的好方法。感谢分享。 – www