easystats / parameters

:bar_chart: Computation and processing of models' parameters
https://easystats.github.io/parameters/
GNU General Public License v3.0
425 stars 36 forks source link

`table_wide` fails with more complex error structures in `aov` objects #556

Open IndrajeetPatil opened 3 years ago

IndrajeetPatil commented 3 years ago

simple error structure

set.seed(123)
library(parameters)
options(error = traceback)

# simple error structure
mod1 <- aov(yield ~ N * P * K + Error(block), npk)

# works
model_parameters(
  mod1,
  eta_squared = "partial",
  ci = 0.95,
  table_wide = TRUE
)
#> # block
#> 
#> Parameter |    F | df | df (error) |     p | Sum_Squares | Mean_Square | Eta2 (partial) |  Eta2 95% CI | Sum_Squares_Error | Mean_Square_Error
#> ----------------------------------------------------------------------------------------------------------------------------------------------
#> N:P:K     | 0.48 |  1 |          4 | 0.525 |       37.00 |       37.00 |           0.11 | [0.00, 0.64] |            306.29 |            306.29
#> 
#> # Within
#> 
#> Parameter |     F | df | df (error) |     p | Sum_Squares | Mean_Square | Eta2 (partial) |  Eta2 95% CI | Sum_Squares_Error | Mean_Square_Error
#> -----------------------------------------------------------------------------------------------------------------------------------------------
#> N         | 12.26 |  1 |         12 | 0.004 |      189.28 |      189.28 |           0.51 | [0.08, 0.74] |            185.29 |            185.29
#> P         |  0.54 |  1 |         12 | 0.475 |        8.40 |        8.40 |           0.04 | [0.00, 0.38] |            185.29 |            185.29
#> K         |  6.17 |  1 |         12 | 0.029 |       95.20 |       95.20 |           0.34 | [0.00, 0.64] |            185.29 |            185.29
#> N:P       |  1.38 |  1 |         12 | 0.263 |       21.28 |       21.28 |           0.10 | [0.00, 0.45] |            185.29 |            185.29
#> N:K       |  2.15 |  1 |         12 | 0.169 |       33.14 |       33.14 |           0.15 | [0.00, 0.50] |            185.29 |            185.29
#> P:K       |  0.03 |  1 |         12 | 0.863 |        0.48 |        0.48 |       2.59e-03 | [0.00, 0.22] |            185.29 |            185.29
#> 
#> Anova Table (Type 1 tests)

more complex error structure

library(ggstatsplot) # for data

mod2 <- stats::aov(
  formula = value ~ attribute * measure + Error(id / (attribute * measure)),
  data = iris_long
)

# {parameters} does return output
model_parameters(
  mod2,
  eta_squared = "partial",
  ci = 0.95
)
#> # id
#> 
#> Parameter | Sum_Squares | df | Mean_Square
#> ------------------------------------------
#> Residuals |      264.01 |  1 |      264.01
#> 
#> # id:attribute
#> 
#> Parameter | Sum_Squares | df | Mean_Square
#> ------------------------------------------
#> attribute |      237.25 |  1 |      237.25
#> 
#> # id:measure
#> 
#> Parameter | Sum_Squares | df | Mean_Square
#> ------------------------------------------
#> measure   |     1113.81 |  1 |     1113.81
#> 
#> # id:attribute:measure
#> 
#> Parameter         | Sum_Squares | df | Mean_Square
#> --------------------------------------------------
#> attribute:measure |        0.80 |  1 |        0.80
#> 
#> # Within
#> 
#> Parameter         | Sum_Squares |  df | Mean_Square |       F |      p | Eta2 (partial) |  Eta2 95% CI
#> ------------------------------------------------------------------------------------------------------
#> attribute         |      470.08 |   1 |      470.08 | 1445.99 | < .001 |           0.71 | [0.68, 0.74]
#> measure           |       57.69 |   1 |       57.69 |  177.46 | < .001 |           0.23 | [0.18, 0.29]
#> attribute:measure |        1.54 |   1 |        1.54 |    4.72 | 0.030  |       7.92e-03 | [0.00, 0.03]
#> Residuals         |      192.46 | 592 |        0.33 |         |        |                |             
#> 
#> Anova Table (Type 1 tests)

# but pivoting it to wider doesn't work
model_parameters(
  mod2,
  eta_squared = "partial",
  ci = 0.95,
  table_wide = TRUE
)
#> Error in `$<-.data.frame`(`*tmp*`, "df_error", value = numeric(0)): replacement has 0 rows, data has 1

Created on 2021-07-16 by the reprex package (v2.0.0)

bwiernik commented 3 years ago

Do we just want to not support table_wide in these cases?

IndrajeetPatil commented 3 years ago

In the tidyverse version of the function I had posted here, it worked.

library(magrittr)

pretty_aov <- function(x) {
  df <- parameters::model_parameters(x, eta_squared = "partial")

  if (class(x)[[1]] %in% c("aov", "aovlist", "anova", "Gam", "manova", "maov")) {
    # creating numerator and denominator degrees of freedom
    if (dim(dplyr::filter(df, Parameter == "Residuals"))[[1]] > 0L) {
      df$df_error <- df$df[nrow(df)]
      df$Sum_Squares_Error <- df$Sum_Squares[nrow(df)]
    }
  }

  # final cleanup
  dplyr::filter(df, !is.na(p)) %>%
    dplyr::select(Parameter, Sum_Squares, Sum_Squares_Error, df, df_error, dplyr::everything())
}

set.seed(123)
mod1 <- aov(yield ~ N * P * K + Error(block), npk)

pretty_aov(mod1)
#> # block
#> 
#> Parameter | Sum_Squares | Sum_Squares_Error | df | df (error) | Mean_Square |    F |     p | Eta2 (partial)
#> -----------------------------------------------------------------------------------------------------------
#> N:P:K     |       37.00 |            185.29 |  1 |         12 |       37.00 | 0.48 | 0.525 |           0.11
#> 
#> # Within
#> 
#> Parameter | Sum_Squares | Sum_Squares_Error | df | df (error) | Mean_Square |     F |     p | Eta2 (partial)
#> ------------------------------------------------------------------------------------------------------------
#> N         |      189.28 |            185.29 |  1 |         12 |      189.28 | 12.26 | 0.004 |           0.51
#> P         |        8.40 |            185.29 |  1 |         12 |        8.40 |  0.54 | 0.475 |           0.04
#> K         |       95.20 |            185.29 |  1 |         12 |       95.20 |  6.17 | 0.029 |           0.34
#> N:P       |       21.28 |            185.29 |  1 |         12 |       21.28 |  1.38 | 0.263 |           0.10
#> N:K       |       33.14 |            185.29 |  1 |         12 |       33.14 |  2.15 | 0.169 |           0.15
#> P:K       |        0.48 |            185.29 |  1 |         12 |        0.48 |  0.03 | 0.863 |       2.59e-03

Created on 2021-08-11 by the reprex package (v2.0.1)

But it doesn't seem to work with the base-R version. We just need to figure out a way to make it work also in the base-R solution.