根据值 'moving window' 范围和比例分类 table?

Classify table based on value 'moving window' range and proportions?

我有一个林分数据集,每个林分包含几个不同年龄和体积的树层。 我想将看台分类为 even-uneven-aged,结合数量和年龄数据。如果超过 80% 的体积分配给相隔 20 年内年龄 类 的森林,则视为 even-aged我想知道如何实现 'within 20 years apart' 条件 ?我可以很容易地计算出体积的总和以及它在各个树层中的份额 (strat)。但是如何检查 'how many years they are apart?' 它是某种移动 window 吗?

虚拟示例:

# investigate volume by age classes?
library(dplyr)

df <- data.frame(stand = c("id1", "id1", "id1", "id1", 
                       'id2', 'id2', 'id2'),
             strat = c(1,2,3,4,
                       1,2,3),
             v = c(4,10,15,20,
                   11,15,18),
             age = c(5,10,65,80,
                     10,15,20))

# even age  = if more of teh 80% of volume is allocated in layers in 20 years range
df %>% 
  group_by(stand) %>% 
  mutate(V_tot = sum(v)) %>% 
  mutate(V_share = v/V_tot*100)

预期结果:

  stand strat     v   age V_tot V_share quality
  <fct> <dbl> <dbl> <dbl> <dbl>   <dbl>
1 id1       1     4     5    49    8.16 uneven-aged
2 id1       2    10    10    49   20.4  uneven-aged
3 id1       3    15    65    49   30.6  uneven-aged
4 id1       4    20    80    49   40.8  uneven-aged #* because age classes 65 and 80, even less then 20 years apart have only 70% of total volume
5 id2       1    11    10    44   25    even-aged
6 id2       2    15    15    44   34.1  even-aged
7 id2       3    18    20    44   40.9  even-aged
    

有趣的问题,我想我有一个使用 runner package

的解决方案
df %>% 
  group_by(stand) %>% 
  mutate(
    V_tot = sum(v),
    V_share = v/V_tot*100,
    test = sum_run(
              V_share,
              k = 20L,
              idx = age,
              na_rm = TRUE,
              na_pad = FALSE
              ),
    quality = if_else(any(test >= 80), 'even-aged', 'uneven-aged')
  ) %>%
  select(-test)

另一种 tidyverse 实现移动平均线的解决方案:

library(tidyverse)

df <- structure(list(stand = c("id1", "id1", "id1", "id1", "id2", "id2", "id2"), strat = c(1, 2, 3, 4, 1, 2, 3), v = c(4, 10, 15, 20, 11, 15, 18), age = c(5, 10, 65, 80, 10, 15, 20), V_tot = c(49, 49, 49, 49, 44, 44, 44), V_share = c(8.16326530612245, 20.4081632653061, 30.6122448979592, 40.8163265306122, 25, 34.0909090909091, 40.9090909090909)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -7L))

df %>% 
  group_by(stand) %>% 
  mutate(range20 = map_dbl(age, ~ sum(V_share[which(abs(age - .x) <= 20)])),
         quality = ifelse(any(range20 > 80), "even-aged", "uneven-aged"))
#> # A tibble: 7 × 8
#> # Groups:   stand [2]
#>   stand strat     v   age V_tot V_share range20 quality    
#>   <chr> <dbl> <dbl> <dbl> <dbl>   <dbl>   <dbl> <chr>      
#> 1 id1       1     4     5    49    8.16    28.6 uneven-aged
#> 2 id1       2    10    10    49   20.4     28.6 uneven-aged
#> 3 id1       3    15    65    49   30.6     71.4 uneven-aged
#> 4 id1       4    20    80    49   40.8     71.4 uneven-aged
#> 5 id2       1    11    10    44   25      100   even-aged  
#> 6 id2       2    15    15    44   34.1    100   even-aged  
#> 7 id2       3    18    20    44   40.9    100   even-aged

reprex package (v2.0.1)

于 2021-09-08 创建