r语言 - 向量化函数的使用,并将单个项连接到单个标题中



标题是模糊的,但让我解释一下:
我有一个非矢量化函数,它输出一个15行树的体积估计表。每行是一个不同的度量单位或输入树的一部分。我有一个Tables参数来帮助用户决定他们要寻找的单位和测量协议,但是在99%的用例场景中,单个树的体积估计的输出是一个包含多行的曲线。

为了演示,我从函数中删除了大约20个其他参数。胸径是树胸高处的直径。Vol列是任意的

Est1 <- TreeVol(Tables = "All", DBH = 7)
Est1
# A tibble: 15 x 3
Tables                                DBH   Vol
<chr>                               <dbl> <dbl>
1 1. Total_Above_Ground_Cubic_Volume      7     2
2 2. Gross_Inter_1/4inch_Vol              7     4
3 3. Net_Scribner_Vol                     7     6
4 4. Gross_Merchantable_Vol               7     8
5 5. Net_Merchantable_Vol                 7    10
6 6. Merchantable_Vol                     7    12
7 7. Gross_SecondaryProduct_Vol           7    14
8 8. Net_SecondaryProduct_Vol             7    16
9 9. SecondaryProduct                     7    18
10 10. Gross_Inter_1/4inch_Vol             7    20
11 11. Net_Inter_1/4inch_Vol               7    22
12 12. Gross_Scribner_SecondaryProduct     7    24
13 13. Net_Scribner_SecondaryProduct       7    26
14 14. Stump_Volume                        7    28
15 15. Tip_Volume                          7    30

用户可以这样使用Tables参数:

Est2 <- TreeVol(Tables = "Scribner_BF", DBH = 7)
# A tibble: 3 x 3
Tables                                DBH   Vol
<chr>                               <dbl> <dbl>
1 3. Net_Scribner_Vol                     7     6
2 12. Gross_Scribner_SecondaryProduct     7    24
3 13. Net_Scribner_SecondaryProduct       7    26

问题出现在,我想写这个函数的矢量化版本,可以计算整个。csv的树库存数据的体积。理想情况下,我希望与单个树相关的多行输出作为一个长目录输出,每个15行默认输出由用户传递给Tables参数的内容过滤,如下所示:

Est3 <- VectorizedTreeVol(Tables = "Scribner_BF", DBH = c(7, 21, 26))
# A tibble: 9 x 3
Tables                                DBH   Vol
<chr>                               <dbl> <dbl>
1 3. Net_Scribner_Vol                     7     6
2 12. Gross_Scribner_SecondaryProduct     7    24
3 13. Net_Scribner_SecondaryProduct       7    26
4 3. Net_Scribner_Vol                     21   18
5 12. Gross_Scribner_SecondaryProduct     21   72
6 13. Net_Scribner_SecondaryProduct       21   76
7 3. Net_Scribner_Vol                     26    8
8 12. Gross_Scribner_SecondaryProduct     26   78
9 13. Net_Scribner_SecondaryProduct       26   84

为了实现这一点,我编写了一个for()循环,作为向量化函数的核心。我听很多人说这种方法效率很低(我也同意),但理论上它符合我想要达到的原则。在这个主题上,我没有找到一个更好的方法来应用于像我这样的矢量化函数。循环的一般设置如下:

for(i in 1:length(DBH)){
Output <- VectorizedTreeVol(Tables = Tables[[i]], DBH = DBH[[i]]) %>% 
purrr::reduce(dplyr::full_join, by = NULL) %>% 
SuppressWarnings()

和在非向量化输出总是单行的函数中,其各自的向量化函数的核心不需要封装在for()循环中,看起来像这样:

Output <- OtherVectorizedFunction(Tables = Tables, DBH = DBH) %>% 
purrr::reduce(dplyr::full_join, by = ColumnNames) %>% #ColumnNames is a vector with all of the output's column names
SuppressWarnings()

reduce()的特定调用在我使用它对项目中的其他函数进行矢量化时工作得很好,但是我对如何连接输出表的建议持开放态度。我已经被这个困境困扰了几个月了,任何关于如何实现这个for()循环在理论上所追求的东西的帮助都是很棒的。有一个矢量化的函数输出像Est3这样的曲线是可能的吗?如有任何反馈意见,我们将不胜感激。

给定此函数:

TreeVol <- function(DBH) {
data.frame(Tables = c("Tree_Vol", "Intercapillary_transfusion", "Woodiness"),
Vol = c(DBH^2, sqrt(DBH) + 3, sin(DBH)),
DBH)
}

我们可以把我们的DBH参数放入purrr::map,然后bind_rows得到一个data.frame。

VecTreeVol <- function(DBH) {
DBH %>%
purrr::map(TreeVol) %>%
bind_rows()
}

结果

> VecTreeVol(DBH = 1:3)
Tables       Vol DBH
1                   Tree_Vol 1.0000000   1
2 Intercapillary_transfusion 4.0000000   1
3                  Woodiness 0.8414710   1
4                   Tree_Vol 4.0000000   2
5 Intercapillary_transfusion 4.4142136   2
6                  Woodiness 0.9092974   2
7                   Tree_Vol 9.0000000   3
8 Intercapillary_transfusion 4.7320508   3
9                  Woodiness 0.1411200   3

最新更新