Creating J Table 2 for Clinical Papers
J Table 2 usually refers to the baseline characteristics table in JAMA-style manuscripts. It is the first table in most clinical research papers and it has a very specific format that reviewers expect. Getting it wrong means going back and redoing the whole thing after a revision request. I have done that more times than I would like to admit. The table presents your study population broken down by exposure groups or comparison groups. Each row is a baseline variable. Each column is a group. The last column shows P-values for differences between groups. That is it structurally. The devil is in the details of how you present each variable type. For categorical variables, you list the count and percentage in parentheses. Something like 45 (32%). Not 32%. The count goes first. If a cell has fewer than 10 observations, some journals require you to switch to median and interquartile range rather than mean and standard deviation. Check your target journal's author guidelines before you start formatting. JAMA does not always require this but many other journals do and editors will flag it during review.
How I usually build it
I generate the table from raw data using R with the jtools package or a custom function built on tableone. The process takes about ten minutes once the script is set up. If you are doing this by hand in Excel you are wasting time and introducing formatting errors. I cannot stress that enough. A single misaligned percentage or a P-value rounded inconsistently across rows will make your table look sloppy to reviewers. Here is what my workflow looks like. I load the cleaned dataset. I define the variable types — continuous, categorical, or ordinal. I specify the grouping variable. I run the tableone function with the appropriate arguments. The output gives me the table in a format that requires minimal adjustment. I then copy it into Word and apply JAMA's column styling. Usually about five minutes of cleanup total.
A problem I ran into and how I fixed it
Once I was submitting to a journal that required exact P-values to four decimal places for all variables. The default tableone output rounds to two or three. I spent about an hour writing a small post-processing function that extracted the raw test statistics from the table object and reformatted them. The key was using the print.tableone function with the printToggle argument set to FALSE so I could access the underlying data frame directly. Then I applied sprintf formatting with the exact decimal precision the journal wanted. It sounds like overkill but it saved me from a revision that would have taken a full day to sort out. The most frequent error is mixing presentation styles within the same table. Some rows show mean and standard deviation. Other rows show median and interquartile range. Pick one approach for continuous variables and stick with it. The second most common issue is failing to account for missing data. Every variable in J Table 2 should show how many observations are missing. If you have 500 patients and only 487 have a lab value recorded, state that. Do not silently drop the missing cases and pretend the denominator is 500. Another thing that trips people up is the P-value calculation method. For continuous variables, use the appropriate test — t-test for normally distributed data, Mann-Whitney U or Kruskal-Wallis for skewed data. For categorical variables, chi-square is standard but if any expected cell count is below five, use Fisher's exact test instead. Report which test you used. Some journals explicitly ask for this in the table footnote.
Get the Full Details

When J Table 2 falls apart
This format works well for straightforward comparisons between two or three groups. It breaks down when you have complex subgroup analyses or when your baseline characteristics include highly correlated variables that need adjusted presentation. I have seen people try to squeeze eight or nine comparison columns into a single J Table 2 and it becomes unreadable. In those cases, split the table into multiple tables. Table 2A for demographics. Table 2B for clinical characteristics. It is cleaner and reviewers prefer it. Also, J Table 2 assumes you are presenting unadjusted baseline characteristics. If your analysis involves propensity score matching or weighting, the baseline table should reflect the weighted or matched sample, not the raw cohort. Presenting the raw cohort in J Table 2 when your primary analysis is on a weighted sample creates a credibility gap that reviewers notice immediately.
Download and tools
There is no single "J Table 2" software to download. It is a formatting convention. However, several R packages will generate properly formatted tables out of the box. tableone is the most widely used. jtools provides additional customization options. For Python users, pingouin and statsmodels can produce the underlying statistics but you will need to handle the formatting yourself. I do not recommend trying to build this from scratch in Excel unless you have no other option and the dataset is tiny. If you want a ready-to-use R script that generates J Table 2 format output with proper handling of continuous and categorical variables, I keep one in my personal repository. It includes the post-processing function I mentioned for custom P-value formatting. It has saved me significant time across multiple manuscripts and it handles the edge cases I described above without requiring manual intervention.
Bottom line
J Table 2 is not complicated but it demands attention to consistency. Get the variable presentation right, use the correct statistical tests, account for missing data, and do not force more information into one table than it can comfortably hold. The format itself is rigid. The flexibility is in how you handle the data that goes into it.
