Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweaking as_gt() #449

Merged
merged 24 commits into from
Aug 12, 2024
Merged

Tweaking as_gt() #449

merged 24 commits into from
Aug 12, 2024

Conversation

yihui
Copy link
Contributor

@yihui yihui commented Aug 9, 2024

I'm looking at the R scripts by alphabetical order, and reduced ~180 lines of code in as_gt(). Again, the changes may be easier to understand if you read the commits one by one.

In some places, I'm using my personal style (e.g., for line breaks and indentation), and happy to follow the style that other colleagues are comfortable with. In general, I tend to make the code a little compact so I can scroll less when reading the code.

I also realized as_rtf()'s source code is very similar to as_gt(), and perhaps can cut out more lines there lines after factoring out the common parts.

@yihui yihui marked this pull request as draft August 9, 2024 17:36
yihui added 21 commits August 9, 2024 12:40
… original code, which is harmless but also unnecessary)
…ing their values in the last unnamed argument, which will be treated as the default
… attributes() and then getting one from the list
… to `switch(method)`; also factor out the phrase 'Bound summary'
…different element via `switch()` for the four methods
…h more readable; also replace `select(all_of(vars))` with `[, vars]`
… them in `content`, `location`, and `attr` for all four methods; also use `if` instead of `ifelse()`, so that we don't need to filter out NA values in the end

note that this introduces whitespace changes in snapshot tests, which are harmless (these spaces are meaningless in LaTeX and HTML)
…ivalent to simply `for (i in seq_along(x))`; the two `if` statements are unnecessary, because if `x` is `NULL` or of length 0, the `for` loop will be skipped

also factor out the footnote location element to the object `loc`, so we don't have to repeat `x %>% gt::tab_footnote()` five times
@jdblischak
Copy link
Collaborator

This is related to #282

I still think that we eventually need to clean up the classes and methods as I noted in #392. However, using switch() for now is definitely a great improvement in readability.

@yihui yihui marked this pull request as ready for review August 9, 2024 17:51
R/ahr_blinded.R Outdated
event = sum(event),
ahr = exp(-theta),
theta = theta,
info0 = sum(event) * (1 - q_e) * q_e
)
return(ans)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I like the explicit return even though it is optional. And checking git blame, I'm pretty sure they existed before I started editing the code base. I'm happy to go along with the consensus though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion here and can definitely use an explicit return(). Personally I use return() only when I need to return early.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LittleBeannie Do you have a preference here? As I said, I'm totally fine with reverting to the original style ans <- ...; return(ans), even though both the assignment and the explicit return() look unnecessary to me.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for verifying, @yihui ! I personally prefer the explicit return, as it provides a clearer message for non-advanced R programmers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. I've restored return() in 90352a0.

Copy link
Collaborator

@LittleBeannie LittleBeannie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @yihui, for tweaking the long as_gt function! I only have 2 minor comments, regarding the error message. Could you please take a look?

}
if (!is.vector(intervals, mode = "numeric") || min(intervals) <= 0) {
stop("ahr_blinded: intervals must be a vector of positive numbers.")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Yihui, I have a question regarding the error message output. Typically, our practice in gsDesign2 is to print the function name at the beginning of the error message. This consideration arises from the possibility that the ahr_blinded function could potentially be invoked within another function. So... I am wondering if we should keep the ahr_blinded here?

Copy link
Contributor Author

@yihui yihui Aug 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I deleted the function name in the error message because I thought it would be redundant.

f = function() foo()
foo = function() {
  stop('No!')
}
f()
#> Error in foo() : No!
foo = function() {
  stop('foo: No!')
}
f()
#> Error in foo() : foo: No!

This relates to a comment I made after #448 (comment) That is, the function name will be missing if you do.call the function.

foo = function() {
  stop('No!')
}
f = function() do.call(foo, list())
f()
#> Error in (function ()  : No!

I think this case is relatively rare (so far we have used do.call() mostly with rbind/cbind in this package). If it does happen, traceback() can be helpful to know the chain of function calls.

That said, again I don't have a strong opinion here. In general, my principle is that I'll follow the preference of the project maintainer (i.e. you in this case).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the clear explanation; I understand your intention. I am open to this. If we choose to remove the function name at the beginning of the error message, we should review the entire gsDesign2 package, as the previous practice of gsDesign2 is to include the function name right at the start (maybe a new issue and PR).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, as I'm going through the whole codebase, I'll do this along the way.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @yihui! This is not urgent and thanks again for reviewing the codes!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I searched the repository for how ahr_blinded() is used. From the package code, examples, and tests, ahr_blinded() is always called directly. In other words, the function itself is never passed as an argument to another function. Thus the fact that an error comes from ahr_blinded() should be clear from the default error message, as @yihui noted above.

To demonstrate, I added stop("there was an error") to ahr_blinded() and generated the error message below:

devtools::load_all()
ahr_blinded(
  surv = survival::Surv(
    time = simtrial::ex2_delayed_effect$month,
    event = simtrial::ex2_delayed_effect$evntd
  ),
  intervals = c(4, 100),
  hr = c(1, .55),
  ratio = 1
)
## Error in ahr_blinded(surv = survival::Surv(time = simtrial::ex2_delayed_effect$month,  : 
##   there was an error

x <- x %>% dplyr::select(dplyr::all_of(display_columns))
}
if (!all(display_columns %in% names(x))) stop(
"not all variable names in 'display_columns' are in the summary_bound object!"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Echo with my previous comment, shall we add as_gt at the beginning of the error message?

@LittleBeannie LittleBeannie self-requested a review August 12, 2024 17:20
Copy link
Collaborator

@jdblischak jdblischak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is looking great. Please see the one switch() statement that needs adjusted.

A bigger picture question for @LittleBeannie and @nanxstats : are we still planning on occasionally running {styler} on the code in {gsDesign2}? The default {styler} format is significantly different than Yihui's preferred style. Below is an example git diff after running {styler} on this PR:

image

R/as_gt.R Show resolved Hide resolved
@LittleBeannie LittleBeannie merged commit 32277b8 into Merck:main Aug 12, 2024
7 checks passed
@yihui yihui deleted the as_gt_tweaks branch August 12, 2024 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants