将功能应用于数据框中的分组行

美国空军

我创建了一个函数,用于计算许多生物统计信息,例如物种范围边缘。这是该函数的简化版本:

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'错误),并且我不确定如何解决该问题。

万维网

由于您添加了dplyr的标记purrr,因此我认为您对tidyverse解决方案感兴趣因此,下面我将演示基于的解决方案tidyverse

首先,你range_stats有问题。这就是为什么您收到错误消息的原因。weighted.mean期望向量为xw参数。但是,如果rangedf为a tibble,则您对tibble诸如进行子集化的方式rangedf[,lat]仍将返回一个单列tibble更好的方法是pulldplyr包装中使用

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.tabledata_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功能的每个组合SPECIESYEAR一种方法是将数据帧拆分为数据帧列表,并使用lapply族功能。但是在这里,我想向您展示如何使用map家庭功能按原样mappurrr软件包中完成此任务,该软件包是的一部分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可以将其与testdfusing合并left_join,但我将在此处停止,因为testresult可能已经是您想要的输出了。我希望这有帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章