2DegreesInvesting / tiltIndicator

Indicators for the TILT project
https://2degreesinvesting.github.io/tiltIndicator/
GNU General Public License v3.0
1 stars 1 forks source link

Test that the output at company level can have `value` other than `0` in "high" AND ("medium" OR "low") #730

Closed maurolepore closed 4 months ago

maurolepore commented 4 months ago

Transfered from https://github.com/2DegreesInvesting/tiltIndicator/pull/639#issuecomment-1956211556 because it stands alone as a separate issue.

--

Create toy datasets that passed to our real code would generate an output at company level with value different than 0 in two of these: "high", "medium", and "low"? For example, I would want value to be c(1/3, 1/3, 1/3) where risk_category is c("high", "medium", NA), respectively.

Conceptually it seems possible as Tilman and Anne "draw" such results but in practice I fail to do that -- even if I create inputs that look almost identical to what they draw. In the best case my failure is simply due to my poor understanding of the data and methodology, but in the worst case it is because of a bug in the code. In any case it will be beneficial to have a conversation with @Tilmon and @AnneSchoenauer about our data and code and turn that conversation into a reproducible example that I can write as a test.

@Tilmon note we're currently working on substantial changes to the code. This means that the results using the main branch (the one you install with the normal installation instructions) are substantially different from the results we expect from our work in progress. So if you attempt to write a reproducible example you may either wait until we merge the ongoing PRs or you install the code directly from the PR with something like this:

# Install the code from this PR: https://github.com/2DegreesInvesting/tiltIndicator/pull/729
pak::pak("2DegreesInvesting/tiltIndicator#729")

If you're struggling with reprex let me konw and we coordinate a meeting.

Tilmon commented 4 months ago

tt01. Hi @maurolepore the installation of the development version doesn't work. Do you know how to fix it? See screenshots below (partially overlapping to give you the full picture):

Image

Image

tt02. Also, could you give me an example how to best create the toy data in a way that it's useful for you? I think what we would need is a company with 3 products with 3 very different co2_footprints to make sure they are in different risk categories. If you could direct me to a similar reprex you created in the past or show me how to best do it, that would be great! Then I'm more than happy to play around with the data.

maurolepore commented 4 months ago

tt01. Yes. The installation above fails because your're trying to install a PR that is already closed (merged). Below I reproduce your error then install the related open PR successfully:

reprex

# This failst because this PR is alredy closed (merged) 
# See https://github.com/2DegreesInvesting/tiltIndicator/pull/729
pak::pak("https://github.com/2DegreesInvesting/tiltIndicator/pull/729")
#> ! Using bundled GitHub PAT. Please add your own PAT using `gitcreds::gitcreds_set()`.
#> Error: ! error in pak subprocess
#> Caused by error: 
#> ! Could not solve package dependencies:
#> * https://github.com/2DegreesInvesting/tiltIndicator/pull/729: ! pkgdepends resolution error for
#> https://github.com/2DegreesInvesting/tiltIndicator/pull/729.
#> Caused by error: 
#> ! no such index at level 5

# That PR merged into this one, which is still open
# https://github.com/2DegreesInvesting/tiltIndicator/pull/639
pak::pak("https://github.com/2DegreesInvesting/tiltIndicator/pull/639")
#> 
#> ✔ Updated metadata database: 4.76 MB in 7 files.
#> 
#> ℹ Updating metadata database
#> ✔ Updating metadata database ... done
#> 
#> 
#> → Will update 1 package.
#> → Will download 1 package with unknown size.
#> + tiltIndicator 0.0.0.9206 → 0.0.0.9206 [bld][cmp][dl] (GitHub: d99e96f)
#> ✔ All system requirements are already installed.
#> 
#> ℹ Getting 1 pkg with unknown size
#> ✔ Got tiltIndicator 0.0.0.9206 (source) (128.78 kB)
#> ℹ Packaging tiltIndicator 0.0.0.9206
#> ✔ Packaged tiltIndicator 0.0.0.9206 (754ms)
#> ℹ Building tiltIndicator 0.0.0.9206
#> ✔ Built tiltIndicator 0.0.0.9206 (3.7s)
#> ✔ Installed tiltIndicator 0.0.0.9206 (github::2DegreesInvesting/tiltIndicator@d99e96f) (36ms)
#> ✔ 1 pkg + 48 deps: kept 47, upd 1, dld 1 (NA B) [18.8s]

Created on 2024-02-23 with reprex v2.1.0

maurolepore commented 4 months ago

tt02. Sure. This thread already helped me to create the tests I needed (see here), but I still encourage you to see the rest of this comment to try understand how you may write your next reprex.

Here I 1) state the expectation, 2) write an example testing the expectation with the smallest possible amount of data and code, 3) state if the actual output meets the expectation or not.

# EXAMPLE OF A REPREX YOU WRITE

# 1. State your expectation:
# At company level, a company with three products with three very different values of `co2_footprint` should yield a non-cero `value` in three different levels of `risk_category`

# 2. Write the simplest possible example

# 2.1 Use as few packages as possible
library(dplyr, warn.conflicts = FALSE)
# It may be important to detail where the code comes from
# pak::pak("2DegreesInvesting/tiltIndicator#639")
library(tiltIndicator)

# It may be important to show the specific package version (e.g. to ensure
# you're using a specific PR)
packageVersion("tiltIndicator")
#> [1] '0.0.0.9207'

# 2.2 Use the smallest and simplest datasets possible
companies <- tribble(
  ~companies_id, ~activity_uuid_product_uuid, ~clustered,
            "a",                         "a",        "a",
            "a",                         "b",        "b",
            "a",                         "c",        "c",
)

# 2.3 Highlight anything important in the initial conditions
# NOTE the values of `co2_footprint` are very different
co2 <- tribble(
  ~activity_uuid_product_uuid, ~co2_footprint, ~isic_4digit, ~unit, ~tilt_sector,
                          "a",              1,     "'1234'",   "a",          "a",
                          "b",           1000,     "'1234'",   "a",          "a",
                          "c",          1e+06,     "'1234'",   "a",          "a",
)

# 2.4 Use the public API (i.e. the funcitons advertised in the website's Reference)
out <- emissions_profile(companies, co2) |> unnest_company()
out
#> # A tibble: 24 × 4
#>    companies_id grouped_by  risk_category value
#>    <chr>        <chr>       <chr>         <dbl>
#>  1 a            all         high          0.333
#>  2 a            all         medium        0.333
#>  3 a            all         low           0.333
#>  4 a            all         <NA>          0    
#>  5 a            isic_4digit high          0.333
#>  6 a            isic_4digit medium        0.333
#>  7 a            isic_4digit low           0.333
#>  8 a            isic_4digit <NA>          0    
#>  9 a            tilt_sector high          0.333
#> 10 a            tilt_sector medium        0.333
#> # ℹ 14 more rows

# 3. Highligth the result that proves if your expectation is met or not This
# meets my expectation: The three products have a non-zero `value` in three
# different levels of `risk_category`
out |> 
  filter(value != 0) |> 
  distinct(risk_category, value)
#> # A tibble: 3 × 2
#>   risk_category value
#>   <chr>         <dbl>
#> 1 high          0.333
#> 2 medium        0.333
#> 3 low           0.333

Created on 2024-02-23 with reprex v2.1.0

--

Then it's super easy for me to turn your reprex into a test and leave it in the package. We run tests every time we do any change so accumulating tests ensures new changes never break desirable old behaviour.

# EXAMPLE OF THE EQUIVALENT TEST I WRITE

test_that("At company level, a company with three products with three very different values of `co2_footprint` should yield a non-cero `value` in three different levels of `risk_category`", {
  companies <- tribble(
    ~companies_id, ~activity_uuid_product_uuid, ~clustered,
              "a",                         "a",        "a",
              "a",                         "b",        "b",
              "a",                         "c",        "c",
  )

  co2 <- tribble(
    ~activity_uuid_product_uuid, ~co2_footprint, ~isic_4digit, ~unit, ~tilt_sector,
                            "a",              1,     "'1234'",   "a",          "a",
                            "b",           1000,     "'1234'",   "a",          "a",
                            "c",          1e+06,     "'1234'",   "a",          "a",
  )

  out <- emissions_profile(companies, co2) |> unnest_company()

  actual <- out |> 
    filter(value != 0) |> 
    distinct(risk_category, value)

  expect_equal(actual$risk_category, c("high", "medium", "low"))
  expect_true(all(actual$value != 0))
})

I hope this makes more transparent the development process and shows how useful it could be for you/Anne to write reprexes for every behaviour you expect, as I can easily translate them to equivalent tests that ensure the software does exactly what you want -- with minimum room for bugs to hide behind misunderstandings.

Learn more

maurolepore commented 4 months ago

Closed by https://github.com/2DegreesInvesting/tiltIndicator/pull/737