report: turning R model output into manuscript prose
:scroll: :tada: Automated reporting of objects in R
At a glance
- What is it?
- report is an R package in the easystats ecosystem that takes a fitted model or a data frame and returns a paragraph of results written in a journal style, with effect sizes and confidence intervals, so the numbers in a paper can be pasted rather than transcribed. It is a formatting tool, not an analysis tool, and the style it enforces is its own.
- Who is it for?
- report suits an R user who writes manuscripts and is tired of transcribing coefficient tables by hand, particularly in fields where the expected result paragraph has a conventional shape, and the fact that it labels effect sizes with an explicit citation is a good sign about the audience it targets.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly R, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap between a fitted model and a results paragraph
The stated primary goal is to bridge the gap between R's output and the formatted results contained in your manuscript. The mechanism is that the package automatically produces reports of models and data frames according to best practices guidelines, with the APA style named as the example, ensuring standardization and quality in results reporting. That framing tells you what the package is and, just as usefully, what it is not. It is not an analysis engine: it does not fit your model, choose your test or decide which effect size to report. It takes an object that already exists, a fitted model, a data frame, a test result, and renders it into sentences. The audience is the researcher who has the numbers and does not want to assemble them into English by hand, which is exactly the step where transcription errors and inconsistent phrasing creep into a manuscript. The project sits inside the wider easystats ecosystem, and the package documentation is published at easystats.github.io/report/.
Two steps: build a report object, then choose how to show it
The workflow is described as working in a two step fashion, and knowing the two steps explains the package's API. First you create a report object with the report() function. Then that object can be displayed in three ways: textually, which is the default output, as a table using as.data.frame(), or as a more digest and compact version using summary() on the report object. That third option matters for real use, because the default prose is often too long to drop into a table cell or a slide, and summary() is how the same object becomes terse. Because the result is an object with methods rather than a printed string, the same analysis can be rendered in several formats without refitting anything. The report() function works on a variety of models as well as other objects such as dataframes, which is what makes the package usable across a manuscript where some paragraphs describe a model and others describe a dataset.
Installing from CRAN and producing the first paragraph
The package is on CRAN and the install is a single call:
install.packages("report")If you would rather experiment with the development version, the README gives the remotes route, which only needs to be done once:
install.packages("remotes")
remotes::install_github("easystats/report") # You only need to do that onceThen load it at the start of each session, and the tip in the documentation is to use library(easystats) instead of library(report) so that all features of the easystats ecosystem are available, with easystats::install_latest() offered as the way to stay updated. A first use is a fitted linear model and one call:
library(report)
model <- lm(Sepal.Length ~ Species, data = iris)
report(model)What comes back is a paragraph that names the model type and estimation method, states the variance explained, gives the intercept with its confidence interval and test statistic, and then lists the effects of each level of the predictor with their coefficients, confidence intervals, t values and p values, closing with a note on how standardized parameters and confidence intervals were obtained. That closing note is a detail worth noticing, because it tells you the package is telling you its own assumptions rather than hiding them.
Data frames, and grouping that survives the pipe
The package also reports data frames, and the example for iris produces a per-variable description with the observation count, mean, standard deviation, median, median absolute deviation, range, skewness, kurtosis and the percentage of missing values, plus a level breakdown for the categorical variable. The design intent is that it fits into the tidyverse workflow rather than sitting beside it. The pipeline example drops the sepal measurements, groups by Species and asks for a summary:
iris %>%
select(-starts_with("Sepal")) %>%
group_by(Species) %>%
report() %>%
summary()The output is organised as one block per group, and each block reports the variables that survived the selection. The reason this is worth an engineering note is that a grouped report is a different object from an ungrouped one, and the group structure is carried through the pipe rather than being applied after the fact. The statistics chosen for a data frame are also a decision, not a default: reporting a median absolute deviation alongside a standard deviation signals that the authors expect heavy-tailed distributions and want the reader to see both.
Effect sizes and the citations behind the wording
The part of the output that most affects how your results read is the effect size, and the package is explicit about which convention it follows in each case. For a t-test, the report notes that effect sizes were labelled following Cohen's 1988 recommendations, and the example output includes a difference with its confidence interval alongside a Cohen's d with its own interval. For an ANOVA, the example states that effect sizes were labelled following Field's 2013 recommendations, and reports an Eta2 with a confidence interval. For a linear model, the output includes standardized betas with their intervals, and the closing sentence explains that standardized parameters were obtained by fitting the model on a standardized version of the dataset and that confidence intervals and p values use a Wald t-distribution approximation. The methodological transparency is deliberate. When a reviewer asks why a value is described as large or substantial, the answer is a citation you can point at, and when you disagree with that convention you at least know which one is in play before you paste the sentence.
Turning a report into a table when the manuscript needs one
Not every result belongs in a paragraph. The README shows the table route with a correlation test piped through report() and then as.data.frame():
cor.test(iris$Sepal.Length, iris$Sepal.Width) %>%
report() %>%
as.data.frame()What comes back is a table with the two parameters, the correlation coefficient, its confidence interval, the test statistic with its degrees of freedom and the p value, with the alternative hypothesis noted underneath. This is the practical reason the package is a report object rather than a string: the same correlation result can be a sentence in one place and a table row in another, and neither requires you to re-run the analysis. The related test example for a t-test follows the same pattern, and an ANOVA is reported with the main effect, its F statistic and p value, and the effect size with its interval. The README also states that reports are compatible with GLMs, though that section is where the available documentation is cut off, so the details of what a GLM report contains are not something this description can vouch for.
Version cadence, the easystats umbrella and the licence
The package is versioned independently of the wider easystats collection, with recent releases v0.6.4 on 2026-05-04, v0.6.3 on 2026-02-04 and v0.6.1 on 2025-02-07, and the last push to the repository was on 2026-10-01. The repository publishes to CRAN, and the README badges point at an R-CMD-check workflow, the r-universe build and the CRAN download counters, which are the standard signals for an R package that is expected to pass CRAN's checks. The source tree is a conventional R package layout with R/, man/, tests/, vignettes/, inst/, a DESCRIPTION file, a NAMESPACE, a NEWS.md changelog and a pkgdown configuration for the documentation site, plus older material kept in an old/ directory and a paper/ directory for the associated manuscript. The licence is the one thing to check before adopting it. GitHub classifies it as Other, a custom licence the platform cannot map to a known identifier, and the repository carries both a LICENSE and a LICENSE.md file, so the terms are not the MIT or GPL text you might assume from the rest of the ecosystem. Read the file rather than inferring from the badge.
Editorial conclusion
report suits an R user who writes manuscripts and is tired of transcribing coefficient tables by hand, particularly in fields where the expected result paragraph has a conventional shape, and the fact that it labels effect sizes with an explicit citation is a good sign about the audience it targets. It is the wrong tool if your target journal has its own house style that the package cannot express, because the output is prose generated by the package rather than a template you control, and it is the wrong tool for anyone who needs the underlying numbers rather than the sentences about them, since the tabular route goes through as.data.frame() and summary() rather than a full reporting API. Verify first which effect size conventions you want, since the examples follow Cohen for t-tests and Field for ANOVA, and check the custom licence at the LICENSE file, because GitHub classifies it as Other and that is a fact to settle before the package lands in a reproducible analysis pipeline.
Frequently asked questions
How do I install the report package in R?
It is on CRAN, so install.packages("report") is enough. For the development version the README gives install.packages("remotes") followed by remotes::install_github("easystats/report"), which only needs to be done once.
What is the difference between report(), summary() and as.data.frame() on a report object?
report() creates the report object, which is then displayed textually by default, as a table with as.data.frame(), or in a more digest and compact form with summary(). The same underlying object is rendered in each case.
Which effect size conventions does report use?
The t-test output states that effect sizes were labelled following Cohen's 1988 recommendations, and the ANOVA output states they follow Field's 2013 recommendations, with a reported Eta2 and confidence interval.
Can report handle data frames as well as models?
Yes. The report() function works on a variety of models as well as other objects such as dataframes, and the iris example reports per-variable statistics including mean, SD, median, MAD, range, skewness, kurtosis and the percentage missing, with a level breakdown for factors.
What licence is the report package under?
GitHub classifies the repository licence as Other, a custom licence it cannot map to a known identifier, and the repository root contains both a LICENSE and a LICENSE.md file.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/easystats-report)Was this useful?