tests/testthat/test-abundance.R

context("abundance")

library(dplyr)

test_that("with cero-lenght dataframe returns a dataframe and result it 0", {
  expect_equal(abundance(tibble()), tibble(n = 0L))
})

describe("abundance", {
  skip_if_not_installed("ctfs")
  abun_ctfs <- function(x, ...) ctfs::abundance(x, ...)$abund$all
  tree_id <- function(x) {
    tibble(
      treeID = as.character(x),
      dbh = 1,
      status = "A",
      date = 800
    )
  }

  it("behaves as ctfs::abundance()", {
    expect_ctfs_equal_to_fgeo <- function(ids) {
      expect_equal(abun_ctfs(tree_id(ids)), abundance(tree_id(ids))$n)
    }
    expect_ctfs_equal_to_fgeo(ids = 1)
    expect_ctfs_equal_to_fgeo(ids = 1:2)

    # Grouped summaries return similar (but are implemented diferently)
    tree <- mutate(tree_id(1:2), sp = letters[1:2])
    expect_equal(
      abun_ctfs(tree, split1 = tree$sp),
      abundance(group_by(tree, sp))$n
    )
  })

  it("Returns consistent output with cero row dataframe", {
    cero_row_dfm <- tree_id(1)[0, ]
    expect_equal(abundance(cero_row_dfm)$n, 0)
    # ctfs's version resuls in dataframe with 0 rows and 0 columns
    expect_equal(abun_ctfs(cero_row_dfm), NULL)
  })

  it("works with both census and ViewFullTable", {
    expect_equal(
      abundance(tree_id(1)),
      abundance(rename(tree_id(1), TreeID = treeID, DBH = dbh))
    )
  })

  it("warns duplicated treeid", {
    expect_warning(
      abundance(mutate(tree_id(c(1, 1)), stemID = c("1.1", "1.2"))),
      "treeid.*Duplicated values.*Do you need to pick main stems?"
    )
  })

  it("warns multiple censusid", {
    expect_warning(
      abundance(mutate(tree_id(c(1, 1)), CensusID = c("1", "2"))),
      "censusid.*Multiple values.*Do you need to group by.*censusid?"
    )
  })

  it("warns multiple plotname", {
    expect_warning(
      abundance(mutate(tree_id(c(1, 1)), PlotName = c("a", "b"))),
      "plotname.*Multiple values.*Do you need to pick a single plot?"
    )
  })

  it("doesn't change the case of input names or groups", {
    tree <- mutate(tree_id(1:2), CensusID = 1:2)
    abund <- abundance(group_by(tree, CensusID))
    expect_named(abund, c("CensusID", "n"))
    expect_equal(group_vars(abund), "CensusID")
  })

  it("returns groups of grouped data", {
    tree <- mutate(tree_id(1:2), CensusID = 1:2)
    expect_true(is_grouped_df(abundance(group_by(tree, CensusID))))
    expect_true(is_grouped_df(basal_area(group_by(tree, CensusID))))
  })
})




context("basal_area")

describe("basal_area", {
  skip_if_not_installed("ctfs")
  ba_ctfs <- function(x, type = "ba", ...) ctfs::abundance(x, type, ...)$ba$all
  tree_id <- function(x) {
    tibble(
      treeID = as.character(x),
      dbh = 1,
      status = "A",
      date = 800
    )
  }

  it("behaves as ctfs::abundance(type = 'ba')", {
    # The reason for an offset is that Condit's funciton outputs basal area in
    # squared meters. Instead, basal_area() does not convert units so the output
    # is in the units of the input -- i.e. generally mm.
    offset <- 1000000
    # numeric
    expect_equal(basal_area(tree_id(1))$basal_area, ba_ctfs(tree_id(1)) * offset)
    # data.frame
    expect_equal(
      basal_area(tree_id(1:2))$basal_area,
      ba_ctfs(tree_id(1:2)) * offset
    )

    # Grouped summaries return similar (but are implemented diferently)
    tree <- mutate(tree_id(1:2), sp = letters[1:2])
    expect_equal(
      basal_area(group_by(tree, sp))$basal_area,
      ba_ctfs(tree, split1 = tree$sp) * offset
    )
  })

  it("warns duplicated stemid", {
    # basal_area warns not treeid but stemid
    expect_warning(
      basal_area(mutate(tree_id(c(1, 1)), stemID = c("1.1", "1.1"))),
      "stemid.*Duplicated values.*Do you need to pick largest.*hom.*values?"
    )
    expect_silent(basal_area(tree_id(c(1, 1))))
  })

  it("warns multiple plotname and censusid", {
    expect_warning(
      basal_area(mutate(tree_id(c(1, 1)), PlotName = c("a", "b"))),
      "plotname.*Multiple values.*Do you need to pick a single plot?"
    )

    expect_warning(
      basal_area(mutate(tree_id(c(1, 1)), CensusID = c("1", "2"))),
      "censusid.*Multiple values.*Do you need to group by.*censusid?"
    )
  })
})

df <- data.frame(
  sp = rep(letters[1:3], each = 2),
  status = rep(c("A", "D"), 3),
  quadrat = 1:6,
  dbh = rnorm(6)
)

test_that("retuns a numeric vector", {
  result <- basal_area_dbl(df$dbh)
  expect_type(result, "double")
  expect_true(rlang::is_vector(result))
})

test_that("returns the expected data structure", {
  result <- basal_area(df)
  expect_type(result, "list")
  expect_true(is.data.frame(basal_area(df)))

  expect_type(basal_area_dbl(df$dbh), "double")
})

test_that("returns the correct sum", {
  df <- data.frame(
    sp = rep(letters[1:3], each = 2),
    status = rep(c("A", "D"), 3),
    quadrat = 1:6,
    dbh = rnorm(6)
  )
  df$ba <- basal_area_dbl(df$dbh)

  actual <- df %>%
    group_by(quadrat) %>%
    basal_area() %>%
    pull(basal_area) %>%
    sum()

  expected <- sum(df$ba)
  expect_equal(actual, expected)
})

test_that("weird arguments throw error", {
  expect_error(basal_area(NULL))
  expect_error(basal_area(NA))
})

test_that("tricky objects in global environment cause no scoping issues", {
  group_by <- c("status") # this should be ignored
  nms <- basal_area(df) %>%
    as_tibble() %>%
    names()
  expect_false("status" %in% nms)
})

test_that("with cero-lenght dataframe returns a dataframe and result it 0", {
  expect_equal(abundance(tibble()), tibble(n = 0L))
})

Try the fgeo.analyze package in your browser

Any scripts or data that you put into this service are public.

fgeo.analyze documentation built on Dec. 5, 2020, 9:06 a.m.