0

Please, consider the following MWE. I'm practicing a technique where I bind the results from several linear models to a data frame (tibble), then apply custom functions (here, grossly simplified for this MWE) to do some rounding/other modifications, then finally pass the tibble to flextable.

library(dplyr)
library(flextable)

# Load example data
data("mtcars")

# Run linear models
model1 <- lm(mpg ~ hp, data = mtcars)
model2 <- lm(mpg ~ hp + wt, data = mtcars)

# Extract the statistics
coef_table1 <- summary(model1)$coefficients["hp", c("Estimate", "Std. Error", "Pr(>|t|)")]
coef_table2 <- summary(model2)$coefficients["hp", c("Estimate", "Std. Error", "Pr(>|t|)")]

# Combine results to matrix; then, convert to tibble
results <- rbind(coef_table1, coef_table2) %>% as_tibble()

# Name the models
results <- results %>% mutate(Model = c("Model1", "Model2")) %>% relocate(Model, .before = Estimate)

# Display results
results %>% flextable()

enter image description here

# Create custom round function for statistics other that p-values
custom_round <- function(x) {
  case_when(
    x >= 0 && x < 0.01 ~ "<.01",
    TRUE ~ paste0(format(round(x, 2), nsmall = 2))
  )
}

# Create custom function for p-values
custom_round_p <- function(x) {
  case_when(
    x >= 0 && x < 0.05 ~ "<.05",
    TRUE ~ paste0(format(round(x, 2), nsmall = 2))
  )
}

# Apply the custom round functions to different sections of
# the results tibble with apply()
results_rounded <- bind_cols(results[1],
                      apply(results[2:3], 2, custom_round),
                      apply(results[4], 2, custom_round_p))

#> Warning in x >= 0 && x < 0.01: 'length(x) = 2 > 1' in coercion to 'logical(1)'

#> Warning in x >= 0 && x < 0.01: 'length(x) = 2 > 1' in coercion to 'logical(1)'

#> Warning in x >= 0 && x < 0.01: 'length(x) = 2 > 1' in coercion to 'logical(1)'
#> Warning in x >= 0 && x < 0.05: 'length(x) = 2 > 1' in coercion to 'logical(1)'

#> Warning in x >= 0 && x < 0.05: 'length(x) = 2 > 1' in coercion to 'logical(1)'

# Display rounded results
results_rounded %>% flextable()

enter image description here

Created on 2023-04-28 (except the flextable parts) with reprex v2.0.2

The code works fine, but apply() throws the above warnings. How much are these of relevance in the usage depicted in this MWE?

jaggedjava
  • 440
  • 6
  • 14
  • Those are serious warnings that shouldn't be ignored. They will be errors once you upgrade to R 4.3.0. The problem is that you are using `&&` when you should be using `&`. – user2554330 Apr 28 '23 at 15:50
  • See https://stackoverflow.com/q/14170778/3358272, https://stackoverflow.com/q/10374932/3358272 – r2evans Apr 28 '23 at 15:51
  • @user2554330, thank you for the comment, you are exactly right, `&&` was something of a typo that I didn't notice myself. @r2evans, thank you for the comment; btw, were you suggesting by giving that link that `ifelse` should be used instead of `case_when`? The problem was caused by `&&`, and `case_when`doesn't seem to cause any errors/warnings. I prefer `case_when` over `ifelse` because I feel `case_when` is more human-readable. – jaggedjava Apr 28 '23 at 17:14

1 Answers1

2

Related duplicate questions:

Fix your code by changing && to &.

custom_round <- function(x) {
  case_when(
    x >= 0 & x < 0.01 ~ "<.01",
    TRUE ~ paste0(format(round(x, 2), nsmall = 2))
  )
}

# Create custom function for p-values
custom_round_p <- function(x) {
  case_when(
    x >= 0 & x < 0.05 ~ "<.05",
    TRUE ~ paste0(format(round(x, 2), nsmall = 2))
  )
}

I also suggest using mutate/across instead of binding apply together.

results %>%
  mutate(
    across(Estimate:`Std. Error`, custom_round),
    `Pr(>|t|)` = custom_round_p(`Pr(>|t|)`)
  )
# # A tibble: 2 × 4
#   Model  Estimate `Std. Error` `Pr(>|t|)`
#   <chr>  <chr>    <chr>        <chr>     
# 1 Model1 -0.07    0.01         <.05      
# 2 Model2 -0.03    <.01         <.05      
r2evans
  • 141,215
  • 6
  • 77
  • 149
  • 1
    Amazing, that `&&` was something of a typo that I had written into the code and reiterated in the second function; I "never" use `&&` intentionally. Big thanks for finding the error in the code - and moreover, optimizing the code elsewhere, too! – jaggedjava Apr 28 '23 at 17:00