Skip to content

Releases: tsostarics/contrastable

contrastable 1.0.2

01 Oct 15:34
Compare
Choose a tag to compare

v0.3.4

17 Sep 23:07
Compare
Choose a tag to compare

User-facing changes

Bug fixes:

  • contr.poly(n), throws an error if n is greater than 95. This caused various functions to fail even with unordered factors with large numbers of factor levels because of the manual check for polynomial contrasts. Now the comparison is only performed if (1) no coding function is provided and (2) n is greater than 95. In situations where an ordered column's contrasts are queried (as in glimpse_contrasts when show_all_factors is TRUE and the column is not set to a non-polynomial scheme) then the error will still be thrown but will be augmented with a helpful message. (#35)
  • glimpse_contrasts no longer shows rownames
  • get_reference_levels works correctly for various types of inputs now
  • various issues with namespacing defused inputs work fine now

New functions:

  • as.unordered is now available, with the implementation largely being the same as base R's as.factor with the added conditional to remove the ordered class from the factor if the factor is ordered. is.unordered was already available.

QOL changes;

  • glimpse_contrasts should be faster now

Backend changes

  • glimpse_contrasts and related functions were refactored and now work much better
  • utility tryMatch is now available, which makes augmenting specific error messages with new messages much simpler. Compare in .get_dimnames (1) below. There is also a related helper stopWithMatch which takes a simpleError and a string (default deparse1(sys.call(1))) and augments the resulting error message. tryMatch can be used in place of tryCatch iff you do not need to run additional code when handling the error and only want to format an error message. stopWithMatch can be used as part of tryCatch, see (2) below.

(1) Much less boilerplate to remember:

tryCatch(dimnames(stats::contrasts(factor_col)),
         error = \(e) {
           err <- conditionMessage(e)
           if (!grepl("cannot be represented accurately", err)) {
             stop(c)
           }
           msg <- paste0("Polynomial contrasts can only be used with <95 levels.\n",
                         "Convert to unordered with  `as.unordered()` or use a non-polynomial scheme")
           stop(paste(err, msg, sep = "\n"))
         })

tryMatch(dimnames(stats::contrasts(factor_col)),
         "cannot be represented accurately" =
           c("Polynomial contrasts can only be used with <95 levels.",
             "Convert to unordered with  `as.unordered` or use a non-polynomial scheme.")
    )

(2) foo() runs additional code, foo2() only uses augmented error messages:

foo <- function(a) {
  tryCatch(a, error = \(e) {
    message("An error! have a random number: ", rnorm(1))
    stopWithMatch(e, "not found" = "how sad!")
  })
}

foo2 <- function(a) {
  tryMatch(a, "not found" = "how sad!")  
}

foo(a + 1)
foo2(a + 1)
> foo(a + 1)
An error! have a random number: -1.27538246066647
Error: In `foo(a+1)`: 
object 'a' not found
ℹ how sad!
> foo2(a + 1)
Error: In `foo2(a+1)`: 
object 'a' not found
ℹ how sad!

v0.3.3

12 Sep 14:03
Compare
Choose a tag to compare

A fair amount of refactoring done with a few breaking changes to use_contrasts, but most people won't use this function directly anyways. Overall, speed should be greatly improved since there is no longer any regular expression checking of the deparsed formulas. Details below.

  • .reset_comparison_labels no longer does manual comparisons for some cherry picked schemes. .process_contrasts will now pass the symbol passed to code_by to use_contrasts, which uses the symbol in the use_contrasts.function method since the function name is lost when doing eval(code_by). This allows .reset_comparison_labels to straightforwardly check the function name as a single string. However, this means that the function must be used to benefit from the automatically generated labels (see below). I think this is fine because the use of the function names should be encouraged, but this does mean that aliased functions can't benefit:
enlist_contrasts(mtcars, carb ~ helmert_code)
# Colnames: <2 <3 <4 <6 <8

cmat <- helmert_code(6)
enlist_contrasts(mtcars, carb ~ cmat)
# Colnames: 2 3 4 6 8


helmert <- helmert_code
enlist_contrasts(mtcars, carb ~ helmert)
# Colnames: 2 3 4 6 8
  • contr.poly and contr.helmert are the only stats-exported contrast functions that are handled by the new .reset_comparison_labels. The former gets the usual polynomial column names as before, but the latter will now denote the scaling factors in the name:
enlist_contrasts(mtcars, carb ~ contr.helmert)
# Colnames: (<2)/2  (<3)/3  (<4)/4  (<6)/5  (<8)/6
  • cumulative_split_code gains special labels now following the ordinal package's notation for threshold coefficients (since that's what inspired this function anyways)
enlist_contrasts(mtcars, carb ~ contr.helmert)
# Colnames:  1|2  2|3  3|4  4|6  6|8
  • .make_parameters has been refactored to use less helper functions. Many of the individual processing steps could be rewritten to follow the same pattern with iterative unnesting of the RHS of the expressions. As a result, many of the formula processing and validation steps could be avoided altogether or handled more elegantly while making the parameters. So, no more regular expression verification of formulas.
  • parse_drop_sequence, .omit_function_calls, .parse_formula, .check_XXX_coding, and .reinstate_dropped_trends (#34) are all obsolete and have been deleted.
  • Because there's no more regex checking of user formulas, the check for an invalid formula where the variable/function name is not the first term on the RHS will now throw an informative error suggesting to check the string (using CLI to give examples). Note that only a few cases of this error are implemented, since depending on the type or class of the object the actual R error might differ. The warnings vignette gives examples of this.
  • The handling of how the - operator is ignored when used with set_contrasts has been redone entirely so avoid regex checking of the deparsed formulas. Now, set_contrasts will apply an attribute that is read by enlist_contrasts, which (if present) will tell .process_contrasts to ignore the - operator.
  • Related to the above, but enlist_contrasts will also return the model data with any factor coercions applied if called within set_contrasts. This changes the potential return value to be either a named list of matrices to a named list containing a list of matrices and a list with a data frame. The standalone use of enlist_contrasts will only ever return the former, and the latter is only used within set_contrasts. This avoids needing to coerce columns twice, which speeds up set_contrasts a bit for large datasets.

v0.3.2

04 Sep 19:25
Compare
Choose a tag to compare

Patch release but also has the breaking change of removing the as_is function in favor of using I() (#31). To my knowledge nobody has been making ample use of as_is anyways, so this is a very very niche change.

v0.3.1

27 Aug 23:07
Compare
Choose a tag to compare

Patch release, mostly documentation updates and refactoring:

  • Formula parsing cleaned up pretty substantially
  • Updated how rlang is imported into the package
  • Citation guide moved to contrasts vignette since it was getting too long

Notable user-facing changes:

  • Default option for verbose has been moved to .onload option option(contrastable.verbose) and is TRUE by default. This can be changed to FALSE for the current R session as needed, or can be set to FALSE on individual function calls.
  • Added option to print contrasts for set_contrasts (#32). When set to TRUE, will print the equivalent of lapply(enlist_contrasts(data, ...), MASS::fractions) for any contrasts that were specified by set_contrasts. Default value is FALSE.
  • A warning is now shown if the dimensions of the contrast matrix passed to interpret_intercept is not n rows by n-1 columns (related to #27)

Bug fixes:

  • glimpse_contrasts when using the namespace resolution operator would throw an error, but is now fixed (#28)
  • hypr package was required to build vignettes, now the relevant code chunks are just not evaluated (#29)
  • Changing the intercept for 2-level factors wasn't working due to an object class error (expected matrix, returned vector), relevant object is now casted to matrix when needed (#27)

v0.3.0

12 Aug 17:59
Compare
Choose a tag to compare
  • Added tidyselect functionality for left-hand side of formulas (#15)
  • is.unordered helper is provided for use with tidyselect functionality
  • Contrast vignette has been rewritten to focus more on the usage of the core functions (#23)
  • A new vignette for common warnings/messages/errors has been added
  • API for decompose_contrasts now uses a one-sided formula (#25)
  • glimpse_contrasts now exhaustively warns when contrasts specified by formulas does not match what's actually set on the dataframe itself (#24)

Bug fixes:

  • For varname ~ foo(), if foo() (with parentheses) is used then foo must be a function in the calling environment. If varname ~ foo is used, then foo can be any valid object. (#26)
  • Setting the intercept for two-level factors works (#27)

v0.2.0, 17 June 2024

16 Jun 20:32
Compare
Choose a tag to compare
v0.2.0, 17 June 2024 Pre-release
Pre-release

Pre-release to create persistent identifier. All functionality can be used as is, but I'll be continuing to update documentation as time allows.