What are reasonable work hours and salary expectations for biostats/genomics careers?

2015-02-12

My advisor recently asked me to fill a career planning document (he'll blog about it at some point) that has lots of questions and is being very useful. Trying to fill answer all these questions has gotten me thinking about other important things for the future. Two of them being reasonable expectations for work hours and salary in a biostats/genomics academic career.

I find these questions hard to answer and even hard to talk about, and if you know me, I'm a person that asks lots of questions. I have also been advised against talking about these subjects during a first interview because it's important to focus on the research environment. I agree that you should find a place to work that you like with problems that will keep you motivated, and with colleagues that make your daily life enjoyable (Hall, 2015).

However, I still want to have a reasonable idea about what to expect. Given that it's hard to ask these questions, it's also hard to blog about it. These questions are not really what others encourage you to talk about (Gould, 2015; Gould, 2014) but I think that I'm not the only one with these questions in mind and that others might benefit from this post. Well, I hope they will.

I didn't ask myself these questions before doing a PhD. It felt natural that doing a PhD would open the door for more opportunities in academia than going to work after undergrad or a masters. Even for a career outside science which a bit more than half (53%) of UK science PhD students choose to follow (Gould, 2014), getting a PhD likely gives a strong boost to your career options. But when you start considering a postdoc, there is an opportunity cost (, 2015) associated to it because you could be earning more at a non-academic job. But how much are we talking about?

Careers

Picture from "The postdoc decision" (Gould, 2014).

Regardless of the opportunity cost of doing a postdoc, for a career in academia you will likely want to do a postdoc to get a chance at a tenure-track job, specially in fields like biology. For a career outside academia but still research related, I think that doing a postdoc could increase your chances at getting a better job. In any case, you have to consider all career options when doing a postdoc (, 2014).

Salary: what to expect

For a postdoc, the NIH sets training stipends which sets a baseline (, 2015). For example, 42k per year in 2014.

For later, ASA: Career Resources for Statisticians has information for biostatistics departments. For example, the median year 0 assistant professor in a biostatistics department made 102k (megan, 2014). From this survey data you can get an idea of the salary progression through your academic career.

Similarly, I find the Life Sciences Salary Survey (2013, 2014) informative. In the 2014 detailed pdf you can see that a male postdoc average pay was $46,372, $79,616 for an assistant professor, $107,868 for associate professors, and $158,059 for professors. That last figure is smaller than $169,900 which is the median salary for year 0 professors in biostatistics (megan, 2014). The 2014 Life Sciences survey also has average salaries by age. So you can make three different progressions of your career salary.

Why should you care?

There are probably many reasons why you should care about your salary given two or more equally good work opportunities. In my case, I wanted to get a rough idea if an academic career would be able to pay for my desired lifestyle and life goals. Let me explain this in more detail.

From looking at the retirement for doctoral scientists report (Foundation, 2015) retiring between 66 and 70 years old seems like a common scenario. Then from the life expectancy calculator (OACT, 2015), it seems that for someone like me the average life expectancy is 87 years and retiring from work at 67 years. That is, about 37 years of work and 20 years of retirement. Then, the average cost of a house is about 320k (McBride, 2014). If you get a house loan for 270k at 4% interest rate for 30 years and 1.25% property tax you would pay 190k in interest and 120k in tax (Unknown, 2015). Federal income tax is about 28% (, 2015) (I know it's more complicated) with about 5% for state tax (, 2015). So about 33% of your income goes to paying taxes. The cost for having a car is about 10k a year (Larry Copeland, 2013) although you could probably save some money by getting a smaller car.

I think that I want to have children in the future, and if I do, I would like to afford their education. It seems that the cost of raising a child to age 18 is about 575k if you spend about 120k in private college (, 2015). Those numbers include the cost of adapting your house (but not interests in mortgage).

I also want to be able to travel quite a bit, and given that these are all US numbers, I would also like to go to Mexico frequently. Anyhow, setting about 5k a year for traveling is an ambitious goal. Alternatively, the 5k could help mitigate any unforeseen emergency, like a surgery.

I can use the numbers from all three academic career salary progressions to get an idea of how my life goals fit in and the impact they would have on my lifestyle. For the average salary for life sciences by age I'm using the numbers from 30 to 67 years old. For average salary for life sciences by career stage I'll use 2 years for postdoc, 7 years for assistant professor, 8 for associate professor and the remaining 20 as a professor. For the progression for biostatistics departments in research universities I simply adapted the above numbers to the greater data resolution available.

Looking at my mint.com budget I see that I spend about 1370 a month on everything except rent. I like my current lifestyle and would like to keep it throughout my life, obviously adapting it to my needs.

Monthly difference between costs for idealized life and current life style (1370 a month) using different salary progression data. That is, how much you can save per month for other misc expenses.
NoChild OneChild TwoChild
average 316 -525 -1366
tenure 1037 197 -644
biostats 2263 1422 581

Now, in the previous table only the life sciences tenure and biostats progressions can handle my life goals without sacrificing my life style if I had one child. Two children only seems feasible in the biostats salary progression. These numbers give a general idea, but it's way more information than I had before.

Note that I'm assuming that your savings can keep up with inflation. Plus, I don't have student loans thanks to receiving my education at UNAM-Mexico, but I know that this isn't true for many US citizens. You could probably do a bit better than I projected if you invested and got a higher return than inflation, got promoted faster, moved to a country with a lower cost of living after saving some money, or had to borrow less money for buying the house. This last point could certainly be feasible if you managed to earn more money early in your career.

Work hours: what to expect

Answering this question has been much harder than the salary question. First, lets look outside of science. A recent news article (, 2015) says: "About 22 percent of Japanese work more than 49 hours a week, compared with 16 percent of Americans, 11 percent of the French and Germans, according to data compiled by the Japanese government."

A different survey shows that 39 percent of full time employed US workers work beyond 49 hours per week with the average being 47 hours (@jenamcgregor, 2014). Broadly summarized government data shows lower averages (, 2015). Anyhow, I think that it's likely that work hours for researchers are in the upper half. I'm also under the impression that most scientists work beyond the official working time (check wiki).

I also agree with the idea that work hours fluctuate, for example with weeks when grants are due reaching high peaks. Also, probably a lot of people haven't tracked their hours (@DynamicEcology, 2014). In my case, using RescueTime I know that I have spent about 45-50 hours per week on my work computer recently (I only have the free version, so I can't go back too far in time). Though I do get distracted at times and my "productivity pulse" is around 60 to 70.

I certainly don't think that scientists should be expected to routinely work 60+ hours a week. There's even a 1943 (wartime) paper arguing that "For men a working week in excess of 60 hours usually leads to no increase in production, and for women the hours should never exceed 54" (see the pdf). But teaching loads can certainly push to higher work loads as this particular story shows (, 2013).

At this point I'm thinking that 45-50 hours per week should be reasonable with a good work-life balance.

But then, "postdocs should expect to work longer-than-average hours" and "We put in the hours we do because it is highly competitive out there" (Gould, 2011).

On the positive side, it seems that research could be a 9-5 job and achieving it "requires good planning, effective teamwork and a supportive environment" (Gould, 2014). This ties in with some of my thoughts: I feel like it's all about being efficient as you can be and indeed having a great work team. So yes, when looking for a job it is very important to find a job with the right research and support environment.

Why should you care?

I think that it's important to know this information so you can have realistic expectations of your stress level and work-life balance. If you underestimate the work load, you'll probably be uncomfortable to say the least.

I also think that it's dangerous to ignore this question even when you are highly motivated by your work and easily lose track of time spent working. That is, I assume that many scientists are motivated by their work but I argue that they should still think about their life outside work.

Alternative way to count

Sleep

Picture from the Sleep Foundation (, 2015).

Another way to take a look at this question is to see how would you like to spend your time outside work. Seems like a good recommendation is to sleep 8 hours per day. Spending about 4 hours per day with your family seems like a good goal (, 2015) although many people can't (, 2015) despite "spending quality family time together is very important" (, 2015). If you exercise about 1 hour a day, take about 1 hour to get ready in the morning, spend 1 hour commuting, and 1 hour cooking/having dinner that leaves you with 8 hours per day for work. With school taking about 6 hours, this seems doable if your work allows you to work from home for 2 hours or so. Such a schedule would look something like this:

  • Wake up at 6:30, exercise 1 hour
  • Get ready: 1 hour
  • Commute: 30 min. You get to work at 9 am.
  • Work 6 hours until 3pm.
  • Commute: 30 min
  • Family time 2 hrs
  • Dinner 1 hour
  • Family time 2 hrs
  • Work 2 more hours: 8:30 to 10:30pm
  • Sleep 8 hours

Now that I think about it, it seems like my advisor is doing something along these lines. Well, he is likely sleeping much less.

Following this type of workday, you would have to work 5-10 hours on the weekend to get to 45-50 work hours per week. Seems doable and reasonable to me. Working beyond 50 hours a week would most likely mean that you'd have to sacrifice family and exercise time. That doesn't seem healthy but I understand that it might be needed at times.

This is when ideas that at first might seem unreasonable start to make some sense. For example, James W. Vaupel suggested working 25 hours a week and retiring later in life so young people get more time with their kids (, 2015).

Conclusions

Learning what to expect in terms of salary and work hours for a biostats/genomics career in academia is challenging and time consuming. At best you depend on surveys which may be biased, information from commercial sites and blog posts. However, with salary progression tables you can get a broad idea of how realistic your life goals and lifestyle expectations are. Although it would be great to have more data and data from other countries. For example, I don't have and haven't looked for the salary progression data in Mexico: maybe salaries are lower but due to lower costs of living you might be better off there than in the US assuming that the research environment is as good or better. That is a question for another time.

I have found some answers which I hope will be useful later on. From the salary perspective, I find it motivating that this career could fund my goals and lifestyle, specially in a Biostatistics department from a research university. From the work hours perspective, at least I have some information to support my previously vague idea that 45-50 hours a week is reasonable. Whether that's enough is yet to be seen. Specially with how competitive it can be to get an academic position and complete the progression to becoming a professor.

But even if tools like the PI predictor (, 2015) say that I have a 10% chance of becoming a PI (data up to nov 2014), I have encountered that all my life: 10% of LCG applicants who passed UNAM's exam got into my undergrad, 10% of applicants got into my PhD program. So it's old news and I just have to keep working to beat the odds.

Reproducibility

Code for making the table:

life_style <- function(progression = 'average', child = 1, tax = .33, retiredyrs = 20, childcost = 575e3, house = 32e4, interest = 19e4, proptax = 12e4, car = 1e4, travel = 5e3) {
    if(progression == 'average') {
        ## Using http://www.the-scientist.com/Nov2014/11_14_SalarySurveyforWeb.pdf
        ## 2014 average compensation in the US for life scientists by age
        sal <- c(58688, 73577, 93946, 108241, 122558, 130551, 139525, 150995)
        yrs <- rep(c(5, 2), c(7, 1))
    } else if (progression == 'tenure') {
        ## Using http://www.the-scientist.com/Nov2014/11_14_SalarySurveyforWeb.pdf
        ## 2014 average male compensation by career stage in academia
        sal <- c(46372, 79616, 107868, 158059)
        yrs <- c(2, 7, 8, 20)
    } else if (progression == 'biostats') {
        ## Using http://magazine.amstat.org/blog/2014/01/01/academic-salary-survey-2/
        ## Work in biostatistics deparments at a research institution
        ## Using life sciences male postdoc average salary as this data is 
        ## missing in this survey.
        sal <- c(46372, 102200, 104000, 105100, 108300, 124700, 129400, 131000, 129700, 169900, 175300, 193400, 235100, 207700, 207900)
        yrs <- c(2, 1, 2, 2, 2, 1, 2, 3, 2, 1, 3, 3, 3, 5, 5)
    } else {
        stop("Invalid 'progression' argument")
    }
    ((sum(sal * yrs) * (1 - tax) - child * childcost - house - interest - proptax) / (sum(yrs) + retiredyrs) - travel - car) / 12
}
progressions <- c('average', 'tenure', 'biostats')
life <- round(data.frame(Progressions = progressions,
    NoChild = sapply(progressions, life_style, child = 0),
    OneChild = sapply(progressions, life_style),
    TwoChild = sapply(progressions, life_style, child = 2),
    row.names = 1
) - 1370, 0)
knitr::kable(life, format = 'html',
    caption = 'Monthly difference between costs for idealized life and current life style (1370 a month) using different salary progression data. That is, how much you can save per month for other misc expenses.'
)

Feel free to play around with life_style() with numbers you think are appropriate for you.

## Reproducibility info
library('devtools')
options(width = 120)
session_info()
## Session info-----------------------------------------------------------------------------------------------------------
##  setting  value                                             
##  version  R Under development (unstable) (2014-11-01 r66923)
##  system   x86_64, darwin10.8.0                              
##  ui       X11                                               
##  language (EN)                                              
##  collate  en_US.UTF-8                                       
##  tz       America/New_York
## Packages---------------------------------------------------------------------------------------------------------------
##  package       * version  date       source                                 
##  bibtex          0.3.6    2013-07-29 CRAN (R 3.2.0)                         
##  devtools      * 1.6.1    2014-10-07 CRAN (R 3.2.0)                         
##  digest          0.6.4    2013-12-03 CRAN (R 3.2.0)                         
##  evaluate        0.5.5    2014-04-29 CRAN (R 3.2.0)                         
##  formatR         1.0      2014-08-25 CRAN (R 3.2.0)                         
##  httr            0.5      2014-09-02 CRAN (R 3.2.0)                         
##  knitcitations * 1.0.4    2014-11-03 Github (cboettig/knitcitations@508de74)
##  knitr         * 1.7      2014-10-13 CRAN (R 3.2.0)                         
##  lubridate       1.3.3    2013-12-31 CRAN (R 3.2.0)                         
##  memoise         0.2.1    2014-04-22 CRAN (R 3.2.0)                         
##  plyr            1.8.1    2014-02-26 CRAN (R 3.2.0)                         
##  Rcpp            0.11.3   2014-09-29 CRAN (R 3.2.0)                         
##  RCurl           1.95.4.3 2014-07-29 CRAN (R 3.2.0)                         
##  RefManageR      0.8.40   2014-10-29 CRAN (R 3.2.0)                         
##  RJSONIO         1.3.0    2014-07-28 CRAN (R 3.2.0)                         
##  rstudioapi      0.1      2014-03-27 CRAN (R 3.2.0)                         
##  stringr         0.6.2    2012-12-06 CRAN (R 3.2.0)                         
##  XML             3.98.1.1 2013-06-20 CRAN (R 3.2.0)

References

Citations made with knitcitations (Boettiger, 2015).

[1] Table B-2. Average weekly hours and overtime of all employees on private nonfarm payrolls by industry sector, seasonally adjusted . http://www.bls.gov/news.release/empsit.t18.htm. 2015. URL: http://www.bls.gov/news.release/empsit.t18.htm.

[2] Cost of Raising a Child Calculator. http://www.babycenter.com/cost-of-raising-child-calculator. 2015. URL: http://www.babycenter.com/cost-of-raising-child-calculator.

[3] Essay on the hours faculty members work each day @insidehighered. https://www.insidehighered.com:80/advice/2013/04/22/essay-hours-faculty-members-work-each-day. 2013. URL: https://www.insidehighered.com:80/advice/2013/04/22/essay-hours-faculty-members-work-each-day.

[4] Gross Pay Calculator. http://www.bankrate.com/calculators/tax-planning/quick-tax-rate-calculator.aspx. 2015. URL: http://www.bankrate.com/calculators/tax-planning/quick-tax-rate-calculator.aspx.

[5] How Much Sleep Do We Really Need? http://sleepfoundation.org/how-sleep-works/how-much-sleep-do-we-really-need. 2015. URL: http://sleepfoundation.org/how-sleep-works/how-much-sleep-do-we-really-need.

[6] News from The Associated Press. http://hosted.ap.org/dynamic/stories/A/AS_WORKAHOLIC_JAPAN. 2015. URL: http://hosted.ap.org/dynamic/stories/A/AS_WORKAHOLIC_JAPAN.

[7] NIH Postdoc Training Stipends. http://www.nationalpostdoc.org/policy/briefing-room/191-nih-stipend-freeze. 2015. URL: http://www.nationalpostdoc.org/policy/briefing-room/191-nih-stipend-freeze.

[8] Opportunity cost - Wikipedia, the free encyclopedia. http://en.wikipedia.org/wiki/Opportunity_cost. 2015. URL: http://en.wikipedia.org/wiki/Opportunity_cost.

[9] pipredictor.com. http://www.pipredictor.com/. 2015. URL: http://www.pipredictor.com/.

[10] Spending quality family time together is very important. http://msue.anr.msu.edu/news/spending_quality_family_time_together_is_very_important. 2015. URL: http://msue.anr.msu.edu/news/spending_quality_family_time_together_is_very_important.

[11] State taxes: Massachusetts | Bankrate.com . http://www.bankrate.com/finance/taxes/state-taxes-massachusetts.aspx. 2015. URL: http://www.bankrate.com/finance/taxes/state-taxes-massachusetts.aspx.

[12] There is life after academia. http://www.nature.com/news/there-is-life-after-academia-1.15808. 2014. URL: http://www.nature.com/news/there-is-life-after-academia-1.15808.

[13] View Poll. http://www.babycenter.com/4_how-much-time-do-you-spend-with-your-kids_1527797.bc. 2015. URL: http://www.babycenter.com/viewPollResults.htm?pollId=1527797.

[14] We should only work 25 hours a week, argues professor. http://sciencenordic.com/we-should-only-work-25-hours-week-argues-professor. 2015. URL: http://sciencenordic.com/we-should-only-work-25-hours-week-argues-professor.

[15] Whether you're a working mom, stay at home mom, or if your child is a baby or in school - how much time do you typically spend with your child in a day? http://www.circleofmoms.com/question/how-much-time-do-you-spend-your-child-day-1701015. 2015. URL: http://www.circleofmoms.com/question/how-much-time-do-you-spend-your-child-day-1701015.

[16] @DynamicEcology. You do not need to work 80 hours a week to succeed in academia. https://dynamicecology.wordpress.com/2014/02/04/you-do-not-need-to-work-80-hours-a-week-to-succeed-in-academia/. 2014. URL: https://dynamicecology.wordpress.com/2014/02/04/you-do-not-need-to-work-80-hours-a-week-to-succeed-in-academia/.

[17] @jenamcgregor. The average work week is now 47 hours. http://www.washingtonpost.com/blogs/on-leadership/wp/2014/09/02/the-average-work-week-is-now-47-hours/. 2014. URL: http://www.washingtonpost.com/blogs/on-leadership/wp/2014/09/02/the-average-work-week-is-now-47-hours/.

[18] C. Boettiger. knitcitations: Citations for knitr markdown files. R package version 1.0.4. 2015. URL: https://github.com/cboettig/knitcitations.

[19] N. S. Foundation. nsf.gov - NCSES The End of Mandatory Retirement for Doctoral Scientists and Engineers in Postsecondary Institutions: Retirement Patterns 10 Years Later - US National Science Foundation (NSF). http://www.nsf.gov/statistics/infbrief/nsf11302/. 2015. URL: http://www.nsf.gov/statistics/infbrief/nsf11302/.

[20] J. Gould. Are long working hours inevitable for postdocs? : Naturejobs Blog. http://blogs.nature.com/naturejobs/2011/04/01/are-long-working-hours-inevitable-for-postdocs. 2011. URL: http://blogs.nature.com/naturejobs/2011/04/01/are-long-working-hours-inevitable-for-postdocs.

[21] J. Gould. Ask the expert: Can research ever be a 9-5 job? : Naturejobs Blog. http://blogs.nature.com/naturejobs/2014/12/18/ask-the-expert-can-research-ever-be-a-9-5-job. 2014. URL: http://blogs.nature.com/naturejobs/2014/12/18/ask-the-expert-can-research-ever-be-a-9-5-job.

[22] J. Gould. Science blogging : Naturejobs Blog. http://blogs.nature.com/naturejobs/2014/09/18/science-blogging. 2014. URL: http://blogs.nature.com/naturejobs/2014/09/18/science-blogging.

[23] J. Gould. Scientific blogging: Why it might just be good for your CV. http://blogs.nature.com/naturejobs/2015/01/30/scientific-blogging-why-it-might-just-be-good-for-your-cv. 2015. URL: http://blogs.nature.com/naturejobs/2015/01/30/scientific-blogging-why-it-might-just-be-good-for-your-cv.

[24] J. Gould. The postdoc decision : Naturejobs Blog. http://blogs.nature.com/naturejobs/2014/10/03/the-postdoc-decision. 2014. URL: http://blogs.nature.com/naturejobs/2014/10/03/the-postdoc-decision.

[25] A. Hall. The Key To Happiness At Work That Has Nothing To Do With Your Actual Job. http://www.huffingtonpost.com/2015/02/04/happiness-at-work_n_6613358.html. 2015. URL: http://www.huffingtonpost.com/2015/02/04/happiness-at-work_n_6613358.html?ncid=fcbklnkushpmg00000063.

[26] U. T. Larry Copeland. The cost of owning your car? \$\\textasciitilde9,000 a year. http://www.usatoday.com/story/news/nation/2013/04/16/aaa-car-ownership-costs/2070397/. 2013. URL: http://www.usatoday.com/story/news/nation/2013/04/16/aaa-car-ownership-costs/2070397/.

[27] B. McBride. Calculated Risk: New Home Prices: New Record for Average and Median in 2013. http://www.calculatedriskblog.com/2014/01/new-home-prices-new-record-for-average.html. 2014. URL: http://www.calculatedriskblog.com/2014/01/new-home-prices-new-record-for-average.html.

[28] megan. Academic Salary Survey | Amstat News. http://magazine.amstat.org/blog/2014/01/01/academic-salary-survey-2/. 2014. URL: http://magazine.amstat.org/blog/2014/01/01/academic-salary-survey-2/.

[29] OACT. Retirement \& Survivors Benefits: Life Expectancy Calculator. http://www.socialsecurity.gov/cgi-bin/longevity.cgi. 2015. URL: http://www.socialsecurity.gov/cgi-bin/longevity.cgi.

[30] Unknown. Unknown. http://www.mortgagecalculator.org/. Accessed 2015-02-12. 2015. URL: http://www.mortgagecalculator.org/.

Want more?

Check other @jhubiostat student blogs at Bmore Biostats as well as topics on #rstats.

Use hidden advanced arguments for user-friendly functions

2014-12-11

As a user

Imagine that you are starting to learn how to use a specific R package, lets call it foo. You will look at the vignette (if there is one), use help(package = foo), or look at the reference manual (for example, devtools' ref man). Eventually, you will open the help page for the function(s) you are interested in using.

?function_I_want_to_use

In many packages, there is a main use case that is addressed by the package. A common strategy is to export a main function. That function will likely have a long list of arguments. So as a new user, you are suddenly exposed to a complicated help page and you will want to figure out which arguments you need to use.

As a developer

From the developer's side, you want to give users control over several details. Each detail you want the user to control involves one more argument in your function. Sooner rather than later, you will have a long list of arguments. This increases the learning curve for new users of your package, and can potentially scare them away. That is contradictory of another goal you have as a developer: you want to get people to use your package.

Lets say that you are developing the function use_me(). If the details you want the users to control are actually arguments of other functions used inside use_me(), then you can simplify your function by using the ... argument. This argument is very well explained at The three-dots construct in R (Burns, 2013). It is very useful and can greatly simplify your life as a developer. Plus, it reduces the length of your help pages, thus making your package more user friendly.

center

However, if some of the details in use_me() are not arguments to other functions, then the common strategy is to write two functions. One is a low level function with arguments for all the details which might or might not export. Then, you write a second function that is a wrapper for the low level function and pre-specifies values for all the details. See the next minimal example:

# Don't export this function
.use_me <- function(arg1, arg2, verbose = TRUE) {
    if(verbose) message(paste(Sys.time(), 'working'))
    pmax(arg1, arg2)
}

#' @export
use_me <- function(arg1, ...) {
    .use_me(arg1, 0, ...)
}

## Lets see it in action
use_me(1:3)
## 2014-12-11 17:03:32 working
## [1] 1 2 3
use_me(-1:1, verbose = FALSE)
## [1] 0 0 1

In this example, the help page for use_me() is fairly short and friendly. You don't expect users to be interested in changing arg2 much. Surely you could make it so the non-exported function .use_me() sets a default value for arg2.

Another strategy is to specify inside use_me() the default values for all the arguments you want to use while keeping the list of visible arguments short. That is, maintain the user friendliness of your functions while also giving them control over all the details. That is what you can do using dots() from dots (Collado-Torres, 2014). dots() is a very simple function that checks if ... has a specific argument, and if absent, it returns a default value. It can be seen in action below:

library('dots')
use_me_dots <- function(arg1, ...) {
    ## Default hidden arguments
    arg2 <- dots(name = 'arg2', value = 0, ...)
    verbose <- dots('verbose', TRUE, ...)
    
    ## Regular code
    if(verbose) message(paste(Sys.time(), 'working'))
    pmax(arg1, arg2)
}
use_me_dots(1:3)
## 2014-12-11 17:03:32 working
## [1] 1 2 3
use_me_dots(-1:1, verbose = FALSE)
## [1] 0 0 1
use_me_dots(-1:1, verbose = FALSE, arg2 = 5)
## [1] 5 5 5

dots is my solution to the problem of keeping functions user friendly while giving them control over all the details. The idea is that experienced users will be able to find what the advanced arguments are. While they could find them from the code itself, I do recommend describing the advanced arguments in a vignette targeted for these users.

Complications

Now, while ... is great, you might run into problems when use_me() calls two functions that have different arguments and that don't have the ... argument. Such a scenario is illustrated below.

status <- function(arg3, status = TRUE) {
    if(status) print(arg3)
    return(invisible(NULL))
}
use_me_again <- function(arg1, ...) {
    res <- .use_me(arg1, 0, ...)
    status(res, ...)
    return(res)
}

## Seems to work
x <- use_me_again(1)
## 2014-12-11 17:03:32 working
## [1] 1
## But nope, it doesn't
use_me_again(1, verbose = FALSE, status = FALSE)
## Error in .use_me(arg1, 0, ...): unused argument (status = FALSE)

This scenario can happen when you are using functions from other packages. It's happened to me in cases where the main function does have a ... argument but uses several internal functions that don't use it.

In such situations, you might want to use formal_call() from dots. It figures out which are the arguments formally used by the function of interest and drops out un-used arguments from ..., thus avoiding this type of problem.

use_me_fixed <- function(arg1, ...) {
    res <- formalCall(.use_me, arg1 = arg1, arg2 = 0, ...)
    formal_call(status, arg3 = res, ...)
    return(res)
}

## Works now!
use_me_fixed(1, verbose = FALSE, status = FALSE)
## [1] 1

For a more complicated example, see the dots complex example in the vignette.

Conclusions

As a developer, it is possible to keep your functions user friendly while giving experienced users the option to control the fine tuning arguments which you don't expect most users will want to tweak. My solution to this problem is implemented in dots (check it's vignette). I'd love to hear what you think about it! I am specially interested on what users think about the idea of hidden advanced arguments (documented in an advanced users vignette).

I might try to get dots into a repository: probably in Bioconductor since most of the dots code was first implemented for derfinder.

PS I just found a similar function to dots(). It's berryFunctions::owa() and you can find its code here.

References

Citations made with knitcitations (Boettiger, 2014).

[1] C. Boettiger. knitcitations: Citations for knitr markdown files. R package version 1.0.4. 2014. URL: https://github.com/cboettig/knitcitations.

[2] P. Burns. The three-dots construct in R - Burns Statistics. http://www.burns-stat.com/the-three-dots-construct-in-r/. 2013. URL: http://www.burns-stat.com/the-three-dots-construct-in-r/.

[3] L. Collado-Torres. dots: Simplifying function calls. R package version 1.0.0. 2014. URL: https://github.com/lcolladotor/dots.

Reproducibility

## Reproducibility info
library('devtools')
options(width = 120)
session_info()
## Session info-----------------------------------------------------------------------------------------------------------
##  setting  value                                             
##  version  R Under development (unstable) (2014-11-01 r66923)
##  system   x86_64, darwin10.8.0                              
##  ui       X11                                               
##  language (EN)                                              
##  collate  en_US.UTF-8                                       
##  tz       America/New_York
## Packages---------------------------------------------------------------------------------------------------------------
##  package       * version  date       source                                 
##  bibtex          0.3.6    2013-07-29 CRAN (R 3.2.0)                         
##  devtools      * 1.6.1    2014-10-07 CRAN (R 3.2.0)                         
##  digest          0.6.4    2013-12-03 CRAN (R 3.2.0)                         
##  dots          * 1.0.0    2014-11-14 Github (lcolladotor/dots@a933540)      
##  evaluate        0.5.5    2014-04-29 CRAN (R 3.2.0)                         
##  formatR         1.0      2014-08-25 CRAN (R 3.2.0)                         
##  httr            0.5      2014-09-02 CRAN (R 3.2.0)                         
##  knitcitations * 1.0.4    2014-11-03 Github (cboettig/knitcitations@508de74)
##  knitr         * 1.7      2014-10-13 CRAN (R 3.2.0)                         
##  lubridate       1.3.3    2013-12-31 CRAN (R 3.2.0)                         
##  memoise         0.2.1    2014-04-22 CRAN (R 3.2.0)                         
##  plyr            1.8.1    2014-02-26 CRAN (R 3.2.0)                         
##  RColorBrewer  * 1.0.5    2011-06-17 CRAN (R 3.2.0)                         
##  Rcpp            0.11.3   2014-09-29 CRAN (R 3.2.0)                         
##  RCurl           1.95.4.3 2014-07-29 CRAN (R 3.2.0)                         
##  RefManageR      0.8.40   2014-10-29 CRAN (R 3.2.0)                         
##  RJSONIO         1.3.0    2014-07-28 CRAN (R 3.2.0)                         
##  rstudioapi      0.1      2014-03-27 CRAN (R 3.2.0)                         
##  stringr         0.6.2    2012-12-06 CRAN (R 3.2.0)                         
##  XML             3.98.1.1 2013-06-20 CRAN (R 3.2.0)

Want more?

Check other @jhubiostat student blogs at Bmore Biostats as well as topics on #rstats.

I wrote dots a month ago and the post itself today during our bi-weekly blog meeting.