{"id":14066276,"url":"https://github.com/insightsengineering/formatters","last_synced_at":"2025-04-12T18:31:52.390Z","repository":{"id":39710160,"uuid":"433597712","full_name":"insightsengineering/formatters","owner":"insightsengineering","description":"A framework for creating listings of raw data that include specialized formatting, headers, footers, referential footnotes, and pagination.","archived":false,"fork":false,"pushed_at":"2025-04-09T13:20:12.000Z","size":33525,"stargazers_count":18,"open_issues_count":22,"forks_count":7,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-04-09T14:31:40.148Z","etag":null,"topics":["format","matrix","r","table"],"latest_commit_sha":null,"homepage":"https://insightsengineering.github.io/formatters/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/insightsengineering.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"custom":["https://pharmaverse.org"]}},"created_at":"2021-11-30T21:53:29.000Z","updated_at":"2025-04-09T13:12:16.000Z","dependencies_parsed_at":"2023-12-20T16:30:36.453Z","dependency_job_id":"5f47ee1f-4690-4302-8e69-27ff14fe15a3","html_url":"https://github.com/insightsengineering/formatters","commit_stats":{"total_commits":194,"total_committers":22,"mean_commits":8.818181818181818,"dds":0.6185567010309279,"last_synced_commit":"3178e6573d5e583e5c06846d00322392f6222131"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insightsengineering%2Fformatters","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insightsengineering%2Fformatters/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insightsengineering%2Fformatters/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insightsengineering%2Fformatters/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/insightsengineering","download_url":"https://codeload.github.com/insightsengineering/formatters/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248613553,"owners_count":21133532,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["format","matrix","r","table"],"created_at":"2024-08-13T07:05:01.377Z","updated_at":"2025-04-12T18:31:52.383Z","avatar_url":"https://github.com/insightsengineering.png","language":"R","funding_links":["https://pharmaverse.org"],"categories":["R"],"sub_categories":[],"readme":"# formatters \u003ca href='https://github.com/insightsengineering/formatters'\u003e\u003cimg src=\"man/figures/logo.svg\" align=\"right\" alt=\"\" width=\"180\"\u003e\u003c/a\u003e\n\n\u003c!-- start badges --\u003e\n[![Check 🛠](https://github.com/insightsengineering/formatters/actions/workflows/check.yaml/badge.svg)](https://insightsengineering.github.io/formatters/main/unit-test-report/)\n[![Docs 📚](https://github.com/insightsengineering/formatters/actions/workflows/docs.yaml/badge.svg)](https://insightsengineering.github.io/formatters/)\n[![Code Coverage 📔](https://raw.githubusercontent.com/insightsengineering/formatters/_xml_coverage_reports/data/main/badge.svg)](https://insightsengineering.github.io/formatters/main/coverage-report/)\n\n![GitHub forks](https://img.shields.io/github/forks/insightsengineering/formatters?style=social)\n![GitHub repo stars](https://img.shields.io/github/stars/insightsengineering/formatters?style=social)\n\n![GitHub commit activity](https://img.shields.io/github/commit-activity/m/insightsengineering/formatters)\n![GitHub contributors](https://img.shields.io/github/contributors/insightsengineering/formatters)\n![GitHub last commit](https://img.shields.io/github/last-commit/insightsengineering/formatters)\n![GitHub pull requests](https://img.shields.io/github/issues-pr/insightsengineering/formatters)\n![GitHub repo size](https://img.shields.io/github/repo-size/insightsengineering/formatters)\n![GitHub language count](https://img.shields.io/github/languages/count/insightsengineering/formatters)\n[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)\n[![Current Version](https://img.shields.io/github/r-package/v/insightsengineering/formatters/main?color=purple\\\u0026label=package%20version)](https://github.com/insightsengineering/formatters/tree/main)\n[![Open Issues](https://img.shields.io/github/issues-raw/insightsengineering/formatters?color=red\\\u0026label=open%20issues)](https://github.com/insightsengineering/formatters/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc)\n\u003c!-- end badges --\u003e\n\nThe `formatters` package provides two core pieces of functionality, both related to ASCII rendering:\n\n1. `format_value` provides the ability to format single- and multi-valued elements into ASCII display-ready strings\n2. the `matrix_form` framework provides generics for implementing ASCII rendering support for display tables\n\nBoth of these feature sets are used in the `rtables` package.\n\n## Motivation\n\nThe core motivation for `formatters` is the rendering of reporting tables into ASCII. In this context a \"value\" is the raw content that to appear in a single table cell. Most commonly this is a numeric vector of length 1, 2 or – occasionally – 3.\n\n## Installation\n\n`formatters` is available on CRAN and you can install the latest released version with:\n\n``` r\ninstall.packages(\"formatters\")\n```\n\nor you can install the latest development version directly from GitHub with:\n\n``` r\n# install.packages(\"pak\")\npak::pak(\"insightsengineering/formatters\")\n```\n\nPackaged releases (both those on CRAN and those between official CRAN releases) can be found in the [releases list](https://github.com/insightsengineering/formatters/releases).\n\nTo understand how to use this package, please refer to the [Introduction to `formatters`](https://insightsengineering.github.io/formatters/latest-tag/articles/formatters.html) article, which provides multiple examples of code implementation.\n\n## Format labels\n\n`formatters` ships with a large number of pre-defined formats appropriate for rendering values into ASCII strings. These existing formats are specified by their labels. We can see the list of these by calling the `list_valid_format_labels` function:\n\n```R\nlist_valid_format_labels()\n\n$`1d`\n [1] \"xx\"                 \"xx.\"                \"xx.x\"\n [4] \"xx.xx\"              \"xx.xxx\"             \"xx.xxxx\"\n [7] \"xx%\"                \"xx.%\"               \"xx.x%\"\n[10] \"xx.xx%\"             \"xx.xxx%\"            \"(N=xx)\"\n[13] \"\u003e999.9\"             \"\u003e999.99\"            \"x.xxxx | (\u003c0.0001)\"\n\n$`2d`\n [1] \"xx / xx\"            \"xx. / xx.\"          \"xx.x / xx.x\"\n [4] \"xx.xx / xx.xx\"      \"xx.xxx / xx.xxx\"    \"xx (xx%)\"\n [7] \"xx (xx.%)\"          \"xx (xx.x%)\"         \"xx (xx.xx%)\"\n[10] \"xx. (xx.%)\"         \"xx.x (xx.x%)\"       \"xx.xx (xx.xx%)\"\n[13] \"(xx, xx)\"           \"(xx., xx.)\"         \"(xx.x, xx.x)\"\n[16] \"(xx.xx, xx.xx)\"     \"(xx.xxx, xx.xxx)\"   \"(xx.xxxx, xx.xxxx)\"\n[19] \"xx - xx\"            \"xx.x - xx.x\"        \"xx.xx - xx.xx\"\n[22] \"xx (xx)\"            \"xx. (xx.)\"          \"xx.x (xx.x)\"\n[25] \"xx.xx (xx.xx)\"      \"xx (xx.)\"           \"xx (xx.x)\"\n[28] \"xx (xx.xx)\"         \"xx.x, xx.x\"         \"xx.x to xx.x\"\n\n$`3d`\n[1] \"xx.xx (xx.xx - xx.xx)\"\n\nattr(,\"info\")\n[1] \"xx does not modify the element, and xx. rounds a number to 0 digits\"\n```\n\nEach of these labels describes how the incoming (possibly multi-element) raw value will be formatted. `xx` indicates that an element of the value will be printed as is, with no modification. `xx.` indicates that a numeric value element will be rounded to 0 decimal places, `xx.x` indicates rounding to 1 decimal place, etc.\n\n## Formatting values\n\nValues are formatted via calls to `format_value`, like so:\n\n```R\nformat_value(5.1235, format = \"xx.xx\")\n\n[1] \"5.12\"\n\nformat_value(c(1.2355, 2.6789), \"(xx.xx, xx.xx)\")\n\n[1] \"(1.24, 2.68)\"\n```\n\n## Table Rendering Framework\n\n__Advanced Usage Only__ These features are supported, and in fact are used in `rtables` and the experimental `rlistings`. That said, the API is currently very low-level and tailored to what `rtables` and `rlistings` need. How useful this is to other table frameworks may vary.\n\nThe second major piece of functionality in `formatters` is the ability to render tables into ASCII (and thus directly to the terminal) based on a so-called `MatrixPrintForm` representation of the table.\n\nTo hook up `rtables`-style ASCII display for your tables, it suffices to export a method for the exported `matrix_form` generic `formatters` provides. This method must return a `MatrixPrintForm` object representing your table.\n\nWe can build a baby example method for `data.frames` to illustrate this process:\n\n```R\n## pagdfrow supports a large number of pieces of information regarding\n## siblings and what information should be repeated after a pagination.\n## we ignore all that here and just give the absolutely crucial info:\n## nm (name), lab (label), rnum (absolute row position), pth (\"path\"),\n## extent (how many lines it takes up), rclass (\"class of row\")\nfake_pagdf_row \u003c- function(i, rnms) {\n    nm \u003c- rnms[i]\n    pagdfrow(nm = nm, lab = nm, rnum = i, pth = nm, extent = 1L,\n             rclass = \"NA\")\n}\n\nmatrix_form.data.frame \u003c- function(df) {\n    fmts \u003c- lapply(df, function(x) if(is.null(obj_format(x))) \"xx\" else obj_format(x))\n\n    bodystrs \u003c- mapply(function(x, fmt) {\n        sapply(x, format_value, format = fmt)\n    }, x = df, fmt = fmts)\n\n    rnms \u003c- row.names(df)\n    if(is.null(rnms))\n        rnms \u003c- as.character(seq_len(NROW(df)))\n\n    cnms \u003c- names(df)\n\n    strings \u003c- rbind(c(\"\", cnms),\n                     cbind(rnms, bodystrs))\n\n    fnr \u003c- nrow(strings)\n    fnc \u003c- ncol(strings)\n\n    ## center alignment for column labels, left alignment for everything else\n    aligns \u003c- rbind(\"center\",\n                    matrix(\"left\", nrow = NROW(df), ncol = fnc))\n    ## build up fake pagination df,\n    rowdf \u003c- basic_pagdf(row.names(df))\n    MatrixPrintForm(strings = strings,\n                      aligns = aligns,\n                      spans = matrix(1, nrow = fnr, ncol = fnc),\n                      formats = NULL,\n                      row_info = rowdf,\n                      has_topleft = FALSE,\n                      nlines_header = 1,\n                      nrow_header = 1)\n}\ncat(toString(matrix_form.data.frame(mtcars)))\n\n                      mpg    cyl   disp    hp    drat    wt     qsec    vs   am   gear   carb\n—————————————————————————————————————————————————————————————————————————————————————————————\nMazda RX4             21     6     160     110   3.9    2.62    16.46   0    1    4      4\nMazda RX4 Wag         21     6     160     110   3.9    2.875   17.02   0    1    4      4\nDatsun 710            22.8   4     108     93    3.85   2.32    18.61   1    1    4      1\nHornet 4 Drive        21.4   6     258     110   3.08   3.215   19.44   1    0    3      1\nHornet Sportabout     18.7   8     360     175   3.15   3.44    17.02   0    0    3      2\nValiant               18.1   6     225     105   2.76   3.46    20.22   1    0    3      1\nDuster 360            14.3   8     360     245   3.21   3.57    15.84   0    0    3      4\nMerc 240D             24.4   4     146.7   62    3.69   3.19    20      1    0    4      2\nMerc 230              22.8   4     140.8   95    3.92   3.15    22.9    1    0    4      2\nMerc 280              19.2   6     167.6   123   3.92   3.44    18.3    1    0    4      4\nMerc 280C             17.8   6     167.6   123   3.92   3.44    18.9    1    0    4      4\nMerc 450SE            16.4   8     275.8   180   3.07   4.07    17.4    0    0    3      3\nMerc 450SL            17.3   8     275.8   180   3.07   3.73    17.6    0    0    3      3\nMerc 450SLC           15.2   8     275.8   180   3.07   3.78    18      0    0    3      3\nCadillac Fleetwood    10.4   8     472     205   2.93   5.25    17.98   0    0    3      4\nLincoln Continental   10.4   8     460     215   3      5.424   17.82   0    0    3      4\nChrysler Imperial     14.7   8     440     230   3.23   5.345   17.42   0    0    3      4\nFiat 128              32.4   4     78.7    66    4.08   2.2     19.47   1    1    4      1\nHonda Civic           30.4   4     75.7    52    4.93   1.615   18.52   1    1    4      2\nToyota Corolla        33.9   4     71.1    65    4.22   1.835   19.9    1    1    4      1\nToyota Corona         21.5   4     120.1   97    3.7    2.465   20.01   1    0    3      1\nDodge Challenger      15.5   8     318     150   2.76   3.52    16.87   0    0    3      2\nAMC Javelin           15.2   8     304     150   3.15   3.435   17.3    0    0    3      2\nCamaro Z28            13.3   8     350     245   3.73   3.84    15.41   0    0    3      4\nPontiac Firebird      19.2   8     400     175   3.08   3.845   17.05   0    0    3      2\nFiat X1-9             27.3   4     79      66    4.08   1.935   18.9    1    1    4      1\nPorsche 914-2         26     4     120.3   91    4.43   2.14    16.7    0    1    5      2\nLotus Europa          30.4   4     95.1    113   3.77   1.513   16.9    1    1    5      2\nFord Pantera L        15.8   8     351     264   4.22   3.17    14.5    0    1    5      4\nFerrari Dino          19.7   6     145     175   3.62   2.77    15.5    0    1    5      6\nMaserati Bora         15     8     301     335   3.54   3.57    14.6    0    1    5      8\nVolvo 142E            21.4   4     121     109   4.11   2.78    18.6    1    1    4      2\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finsightsengineering%2Fformatters","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finsightsengineering%2Fformatters","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finsightsengineering%2Fformatters/lists"}