{"id":15292966,"url":"https://github.com/jorischau/rrapply","last_synced_at":"2025-09-02T11:38:00.416Z","repository":{"id":47117495,"uuid":"261768665","full_name":"JorisChau/rrapply","owner":"JorisChau","description":"rrapply: revisiting base-R's rapply","archived":false,"fork":false,"pushed_at":"2025-01-02T16:35:23.000Z","size":8686,"stargazers_count":58,"open_issues_count":2,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-31T18:40:00.231Z","etag":null,"topics":["list","r","rapply","recursion"],"latest_commit_sha":null,"homepage":"https://jorischau.github.io/rrapply/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JorisChau.png","metadata":{"files":{"readme":"README.md","changelog":"NEWS.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-05-06T13:34:39.000Z","updated_at":"2025-06-01T08:29:39.000Z","dependencies_parsed_at":"2025-04-13T12:14:13.033Z","dependency_job_id":"c2ed8486-cafa-4126-a5d8-086cef0c78ce","html_url":"https://github.com/JorisChau/rrapply","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/JorisChau/rrapply","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JorisChau%2Frrapply","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JorisChau%2Frrapply/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JorisChau%2Frrapply/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JorisChau%2Frrapply/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JorisChau","download_url":"https://codeload.github.com/JorisChau/rrapply/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JorisChau%2Frrapply/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273279106,"owners_count":25077309,"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","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["list","r","rapply","recursion"],"created_at":"2024-09-30T16:36:44.118Z","updated_at":"2025-09-02T11:38:00.372Z","avatar_url":"https://github.com/JorisChau.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n# {rrapply}: Revisiting R-base rapply() \u003cimg style=\"height: 139px;\" src='sticker.svg' align=\"right\" /\u003e\n\n\u003c!-- badges: start --\u003e\n\n[![CRAN\nversion](https://www.r-pkg.org/badges/version/rrapply)](https://cran.r-project.org/package=rrapply)\n[![R-CMD-check](https://github.com/JorisChau/rrapply/workflows/R-CMD-check/badge.svg)](https://github.com/JorisChau/rrapply/actions)\n[![codecov](https://codecov.io/gh/JorisChau/rrapply/branch/master/graph/badge.svg)](https://app.codecov.io/gh/JorisChau/rrapply)\n[![status](https://tinyverse.netlify.app/badge/rrapply)](https://CRAN.R-project.org/package=rrapply)\n[![Total\nDownloads](https://cranlogs.r-pkg.org/badges/grand-total/rrapply)](https://cran.r-project.org/package=rrapply)\n\u003c!-- badges: end --\u003e\n\nThe minimal {rrapply}-package contains a single function `rrapply()`,\nproviding an extended implementation of R-base’s `rapply()` function,\nwhich applies a function `f` to all elements of a nested list\nrecursively and controls how to structure the returned result.\n`rrapply()` builds upon `rapply()`’s native C implementation and for\nthis reason requires no external R-package dependencies.\n\n## Installation\n\n``` r\n# Install latest release from CRAN:\ninstall.packages(\"rrapply\")\n\n# Install the development version from GitHub:\n# install.packages(\"devtools\")\ndevtools::install_github(\"JorisChau/rrapply\")\n```\n\n## Cheat sheet\n\n\u003cdiv\u003e\n\n\u003ca href='https://github.com/JorisChau/rrapply/blob/master/vignettes/cheatsheet.pdf'\u003e\n\u003cimg src='cheatsheet.svg' align=\"center\" height=\"600\" /\u003e \u003c/a\u003e\n\n\u003c/div\u003e\n\n## When to use `rrapply()`\n\n### List pruning and unnesting\n\n#### • `how = \"prune\"`\n\nWith base `rapply()`, there is no convenient way to prune or filter list\nelements from the input list object. The `rrapply()` function adds an\noption `how = \"prune\"` to prune all list elements not subject to\napplication of `f` from a nested list,\n\n``` r\nlibrary(rrapply)\n\n## data: renewable energy per country in 2016 (% of total energy consumption)\ndata(\"renewable_energy_by_country\")\n\n## subset countries and areas in Oceania\nrenewable_oceania \u003c- renewable_energy_by_country[[\"World\"]][\"Oceania\"]\nstr(renewable_oceania, list.len = 3, give.attr = FALSE)\n\n#\u003e List of 1\n#\u003e  $ Oceania:List of 4\n#\u003e   ..$ Australia and New Zealand:List of 6\n#\u003e   .. ..$ Australia                        : num 9.32\n#\u003e   .. ..$ Christmas Island                 : logi NA\n#\u003e   .. ..$ Cocos (Keeling) Islands          : logi NA\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ Melanesia                :List of 5\n#\u003e   .. ..$ Fiji            : num 24.4\n#\u003e   .. ..$ New Caledonia   : num 4.03\n#\u003e   .. ..$ Papua New Guinea: num 50.3\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ Micronesia               :List of 8\n#\u003e   .. ..$ Guam                                : num 3.03\n#\u003e   .. ..$ Kiribati                            : num 45.4\n#\u003e   .. ..$ Marshall Islands                    : num 11.8\n#\u003e   .. .. [list output truncated]\n#\u003e   .. [list output truncated]\n```\n\n``` r\n## drop all logical NA's while preserving list structure \nrrapply(\n  renewable_oceania,\n  f = \\(x) x,\n  classes = \"numeric\",\n  how = \"prune\"\n) |\u003e\n  str(list.len = 3, give.attr = FALSE)\n\n#\u003e List of 1\n#\u003e  $ Oceania:List of 4\n#\u003e   ..$ Australia and New Zealand:List of 2\n#\u003e   .. ..$ Australia  : num 9.32\n#\u003e   .. ..$ New Zealand: num 32.8\n#\u003e   ..$ Melanesia                :List of 5\n#\u003e   .. ..$ Fiji            : num 24.4\n#\u003e   .. ..$ New Caledonia   : num 4.03\n#\u003e   .. ..$ Papua New Guinea: num 50.3\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ Micronesia               :List of 7\n#\u003e   .. ..$ Guam                            : num 3.03\n#\u003e   .. ..$ Kiribati                        : num 45.4\n#\u003e   .. ..$ Marshall Islands                : num 11.8\n#\u003e   .. .. [list output truncated]\n#\u003e   .. [list output truncated]\n```\n\n#### • `how = \"flatten\"`\n\nInstead, use `how = \"flatten\"` to return a flattened unnested version of\nthe pruned list,\n\n``` r\n## drop all logical NA's and return unnested list\nrrapply(\n  renewable_oceania,\n  f = \\(x) x,\n  classes = \"numeric\",\n  how = \"flatten\"\n) |\u003e\n  head(n = 10)\n\n#\u003e        Australia      New Zealand             Fiji    New Caledonia \n#\u003e             9.32            32.76            24.36             4.03 \n#\u003e Papua New Guinea  Solomon Islands          Vanuatu             Guam \n#\u003e            50.34            65.73            33.67             3.03 \n#\u003e         Kiribati Marshall Islands \n#\u003e            45.43            11.75\n```\n\n**Hint**: the `options` argument allows to avoid coercion of the\nflattened list to a vector and/or to include all parent list names in\nthe result.\n\n``` r\n## flatten to simple list with full names\nrrapply(\n  renewable_oceania,\n  f = \\(x) x,\n  classes = \"numeric\",\n  how = \"flatten\",\n  options = list(namesep = \".\", simplify = FALSE)\n) |\u003e\n  str(list.len = 5, give.attr = FALSE)\n\n#\u003e List of 22\n#\u003e  $ Oceania.Australia and New Zealand.Australia        : num 9.32\n#\u003e  $ Oceania.Australia and New Zealand.New Zealand      : num 32.8\n#\u003e  $ Oceania.Melanesia.Fiji                             : num 24.4\n#\u003e  $ Oceania.Melanesia.New Caledonia                    : num 4.03\n#\u003e  $ Oceania.Melanesia.Papua New Guinea                 : num 50.3\n#\u003e   [list output truncated]\n```\n\n#### • `how = \"melt\"`\n\nOr, use `how = \"melt\"` to return a melted data.frame of the pruned list\nsimilar in format to `reshape2::melt()` applied to a nested list.\n\n``` r\n## drop all logical NA's and return melted data.frame\noceania_melt \u003c- rrapply(\n  renewable_oceania,\n  f = \\(x) x,\n  classes = \"numeric\",\n  how = \"melt\"\n)\nhead(oceania_melt)\n\n#\u003e        L1                        L2               L3 value\n#\u003e 1 Oceania Australia and New Zealand        Australia  9.32\n#\u003e 2 Oceania Australia and New Zealand      New Zealand 32.76\n#\u003e 3 Oceania                 Melanesia             Fiji 24.36\n#\u003e 4 Oceania                 Melanesia    New Caledonia  4.03\n#\u003e 5 Oceania                 Melanesia Papua New Guinea 50.34\n#\u003e 6 Oceania                 Melanesia  Solomon Islands 65.73\n```\n\nA melted data.frame can be used to reconstruct a nested list with\n`how = \"unmelt\"`,\n\n``` r\n## reconstruct nested list from melted data.frame\nrrapply(oceania_melt, how = \"unmelt\") |\u003e\n  str(list.len = 3, give.attr = FALSE)\n\n#\u003e List of 1\n#\u003e  $ Oceania:List of 4\n#\u003e   ..$ Australia and New Zealand:List of 2\n#\u003e   .. ..$ Australia  : num 9.32\n#\u003e   .. ..$ New Zealand: num 32.8\n#\u003e   ..$ Melanesia                :List of 5\n#\u003e   .. ..$ Fiji            : num 24.4\n#\u003e   .. ..$ New Caledonia   : num 4.03\n#\u003e   .. ..$ Papua New Guinea: num 50.3\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ Micronesia               :List of 7\n#\u003e   .. ..$ Guam                            : num 3.03\n#\u003e   .. ..$ Kiribati                        : num 45.4\n#\u003e   .. ..$ Marshall Islands                : num 11.8\n#\u003e   .. .. [list output truncated]\n#\u003e   .. [list output truncated]\n```\n\n#### • `how = \"bind\"`\n\nNested lists containing repeated observations can be unnested with\n`how = \"bind\"`, which returns a wide data.frame similar in format to\n`dplyr::bind_rows()` applied to a list of data.frames or repeated\napplication of `tidyr::unnest_wider()` to a nested data.frame.\n\n``` r\n## data: nested list of Pokemon properties in Pokemon GO\ndata(\"pokedex\")\nstr(pokedex, list.len = 3)\n\n#\u003e List of 1\n#\u003e  $ pokemon:List of 151\n#\u003e   ..$ :List of 16\n#\u003e   .. ..$ id            : int 1\n#\u003e   .. ..$ num           : chr \"001\"\n#\u003e   .. ..$ name          : chr \"Bulbasaur\"\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ :List of 17\n#\u003e   .. ..$ id            : int 2\n#\u003e   .. ..$ num           : chr \"002\"\n#\u003e   .. ..$ name          : chr \"Ivysaur\"\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ :List of 15\n#\u003e   .. ..$ id            : int 3\n#\u003e   .. ..$ num           : chr \"003\"\n#\u003e   .. ..$ name          : chr \"Venusaur\"\n#\u003e   .. .. [list output truncated]\n#\u003e   .. [list output truncated]\n```\n\n``` r\n## unnest list to wide data.frame\nrrapply(pokedex, how = \"bind\")[, c(1:3, 5:8)] |\u003e\n  head(n = 9)\n\n#\u003e   id num       name          type height   weight            candy\n#\u003e 1  1 001  Bulbasaur Grass, Poison 0.71 m   6.9 kg  Bulbasaur Candy\n#\u003e 2  2 002    Ivysaur Grass, Poison 0.99 m  13.0 kg  Bulbasaur Candy\n#\u003e 3  3 003   Venusaur Grass, Poison 2.01 m 100.0 kg  Bulbasaur Candy\n#\u003e 4  4 004 Charmander          Fire 0.61 m   8.5 kg Charmander Candy\n#\u003e 5  5 005 Charmeleon          Fire 1.09 m  19.0 kg Charmander Candy\n#\u003e 6  6 006  Charizard  Fire, Flying 1.70 m  90.5 kg Charmander Candy\n#\u003e 7  7 007   Squirtle         Water 0.51 m   9.0 kg   Squirtle Candy\n#\u003e 8  8 008  Wartortle         Water 0.99 m  22.5 kg   Squirtle Candy\n#\u003e 9  9 009  Blastoise         Water 1.60 m  85.5 kg   Squirtle Candy\n```\n\n**Hint**: set `options = list(namecols = TRUE)` to include the parent\nlist names associated to each row in the wide data.frame as individual\ncolumns `L1`, `L2`, etc.\n\n``` r\n## bind to data.frame including parent columns\nrrapply(pokedex, how = \"bind\", options = list(namecols = TRUE))[, c(1:5, 7:10)] |\u003e\n  head(n = 6)\n\n#\u003e        L1 L2 id num       name          type height   weight            candy\n#\u003e 1 pokemon  1  1 001  Bulbasaur Grass, Poison 0.71 m   6.9 kg  Bulbasaur Candy\n#\u003e 2 pokemon  2  2 002    Ivysaur Grass, Poison 0.99 m  13.0 kg  Bulbasaur Candy\n#\u003e 3 pokemon  3  3 003   Venusaur Grass, Poison 2.01 m 100.0 kg  Bulbasaur Candy\n#\u003e 4 pokemon  4  4 004 Charmander          Fire 0.61 m   8.5 kg Charmander Candy\n#\u003e 5 pokemon  5  5 005 Charmeleon          Fire 1.09 m  19.0 kg Charmander Candy\n#\u003e 6 pokemon  6  6 006  Charizard  Fire, Flying 1.70 m  90.5 kg Charmander Candy\n```\n\n### Condition function\n\nBase `rapply()` allows to apply a function `f` to list elements of\ncertain types or classes via the `classes` argument. `rrapply()`\ngeneralizes this option via an additional `condition` argument, which\naccepts any function to use as a condition or predicate to apply `f` to\na subset of list elements.\n\n``` r\n## drop all NA elements using condition \nrrapply(\n  renewable_oceania,\n  condition = \\(x) !is.na(x),\n  f = \\(x) x,\n  how = \"prune\"\n) |\u003e\n  str(list.len = 3, give.attr = FALSE)\n\n#\u003e List of 1\n#\u003e  $ Oceania:List of 4\n#\u003e   ..$ Australia and New Zealand:List of 2\n#\u003e   .. ..$ Australia  : num 9.32\n#\u003e   .. ..$ New Zealand: num 32.8\n#\u003e   ..$ Melanesia                :List of 5\n#\u003e   .. ..$ Fiji            : num 24.4\n#\u003e   .. ..$ New Caledonia   : num 4.03\n#\u003e   .. ..$ Papua New Guinea: num 50.3\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ Micronesia               :List of 7\n#\u003e   .. ..$ Guam                            : num 3.03\n#\u003e   .. ..$ Kiribati                        : num 45.4\n#\u003e   .. ..$ Marshall Islands                : num 11.8\n#\u003e   .. .. [list output truncated]\n#\u003e   .. [list output truncated]\n```\n\n``` r\n## filter all countries with values \u003e 85%\nrrapply(\n  renewable_energy_by_country,\n  condition = \\(x) x \u003e 85,\n  how = \"prune\"\n) |\u003e\n  str(give.attr = FALSE)\n\n#\u003e List of 1\n#\u003e  $ World:List of 1\n#\u003e   ..$ Africa:List of 1\n#\u003e   .. ..$ Sub-Saharan Africa:List of 3\n#\u003e   .. .. ..$ Eastern Africa:List of 7\n#\u003e   .. .. .. ..$ Burundi                    : num 89.2\n#\u003e   .. .. .. ..$ Ethiopia                   : num 91.9\n#\u003e   .. .. .. ..$ Rwanda                     : num 86\n#\u003e   .. .. .. ..$ Somalia                    : num 94.7\n#\u003e   .. .. .. ..$ Uganda                     : num 88.6\n#\u003e   .. .. .. ..$ United Republic of Tanzania: num 86.1\n#\u003e   .. .. .. ..$ Zambia                     : num 88.5\n#\u003e   .. .. ..$ Middle Africa :List of 2\n#\u003e   .. .. .. ..$ Chad                            : num 85.3\n#\u003e   .. .. .. ..$ Democratic Republic of the Congo: num 97\n#\u003e   .. .. ..$ Western Africa:List of 1\n#\u003e   .. .. .. ..$ Guinea-Bissau: num 86.5\n```\n\n### Special arguments `.xname`, `.xpos`, `.xparents` and `.xsiblings`\n\nWith base `rapply()`, the `f` function only has access to the *content*\nof the list element under evaluation, and there is no convenient way to\naccess its name or location in the nested list from inside `f`.\n`rrapply()` defines the special arguments `.xname`, `.xpos`,\n`.xparents`, `.xsiblings` inside the `f` and `condition` functions (in\naddition to the principal function argument):\n\n- `.xname` evaluates to the name of the list element;\n- `.xpos` evaluates to the position of the element in the nested list\n  structured as an integer vector;\n- `.xparents` evaluates to a vector of parent list names in the path to\n  the current list element;\n- `.xsiblings` evaluates to the parent list containing the current list\n  element and its direct siblings.\n\n``` r\n## apply f based on element's name\nrrapply(\n  renewable_oceania,\n  condition = \\(x) !is.na(x),\n  f = \\(x, .xname) sprintf(\"Renewable energy in %s: %.2f%%\", .xname, x),\n  how = \"flatten\"\n) |\u003e\n  head(n = 5)\n\n#\u003e                                      Australia \n#\u003e         \"Renewable energy in Australia: 9.32%\" \n#\u003e                                    New Zealand \n#\u003e      \"Renewable energy in New Zealand: 32.76%\" \n#\u003e                                           Fiji \n#\u003e             \"Renewable energy in Fiji: 24.36%\" \n#\u003e                                  New Caledonia \n#\u003e     \"Renewable energy in New Caledonia: 4.03%\" \n#\u003e                               Papua New Guinea \n#\u003e \"Renewable energy in Papua New Guinea: 50.34%\"\n\n## filter elements by name \nrrapply(\n  renewable_energy_by_country,\n  condition = \\(x, .xname) .xname %in% c(\"Belgium\", \"Netherlands\", \"Luxembourg\"),\n  how = \"prune\"\n) |\u003e\n  str(give.attr = FALSE)\n\n#\u003e List of 1\n#\u003e  $ World:List of 1\n#\u003e   ..$ Europe:List of 1\n#\u003e   .. ..$ Western Europe:List of 3\n#\u003e   .. .. ..$ Belgium    : num 9.14\n#\u003e   .. .. ..$ Luxembourg : num 13.5\n#\u003e   .. .. ..$ Netherlands: num 5.78\n\n## filter European countries \u003e 50% using .xpos\nrrapply(\n  renewable_energy_by_country,\n  condition = \\(x, .xpos) identical(.xpos[1:2], c(1L, 5L)) \u0026\u0026 x \u003e 50,\n  how = \"prune\"\n) |\u003e\n  str(give.attr = FALSE)\n\n#\u003e List of 1\n#\u003e  $ World:List of 1\n#\u003e   ..$ Europe:List of 2\n#\u003e   .. ..$ Northern Europe:List of 3\n#\u003e   .. .. ..$ Iceland: num 78.1\n#\u003e   .. .. ..$ Norway : num 59.5\n#\u003e   .. .. ..$ Sweden : num 51.4\n#\u003e   .. ..$ Western Europe :List of 1\n#\u003e   .. .. ..$ Liechtenstein: num 62.9\n\n## filter European countries \u003e 50% using .xparents\nrrapply(\n  renewable_energy_by_country, \n  condition = \\(x, .xparents) \"Europe\" %in% .xparents \u0026\u0026 x \u003e 50,\n  how = \"prune\"\n) |\u003e\n  str(give.attr = FALSE)\n\n#\u003e List of 1\n#\u003e  $ World:List of 1\n#\u003e   ..$ Europe:List of 2\n#\u003e   .. ..$ Northern Europe:List of 3\n#\u003e   .. .. ..$ Iceland: num 78.1\n#\u003e   .. .. ..$ Norway : num 59.5\n#\u003e   .. .. ..$ Sweden : num 51.4\n#\u003e   .. ..$ Western Europe :List of 1\n#\u003e   .. .. ..$ Liechtenstein: num 62.9\n\n## return position of element in list\nrrapply(\n  renewable_energy_by_country,\n  condition = \\(x, .xname) .xname == \"Sweden\",\n  f = \\(x, .xpos) .xpos,\n  how = \"flatten\"\n)\n\n#\u003e $Sweden\n#\u003e [1]  1  5  2 14\n\n## return siblings of element in list\nrrapply(\n  renewable_energy_by_country,\n  condition = \\(x, .xsiblings) \"Sweden\" %in% names(.xsiblings),\n  how = \"flatten\"\n) |\u003e\n  head(n = 5)\n\n#\u003e Aland Islands       Denmark       Estonia Faroe Islands       Finland \n#\u003e            NA         33.06         26.55          4.24         42.03\n\n## filter elements and unnest list  \nrrapply(\n  pokedex,\n  condition = \\(x, .xpos, .xname) length(.xpos) \u003c 4 \u0026 .xname %in% c(\"num\", \"name\", \"type\"),\n  how = \"bind\"\n) |\u003e\n  head()\n\n#\u003e   num       name          type\n#\u003e 1 001  Bulbasaur Grass, Poison\n#\u003e 2 002    Ivysaur Grass, Poison\n#\u003e 3 003   Venusaur Grass, Poison\n#\u003e 4 004 Charmander          Fire\n#\u003e 5 005 Charmeleon          Fire\n#\u003e 6 006  Charizard  Fire, Flying\n```\n\n### Modifying list elements\n\nBy default, both base `rapply()` and `rrapply()` recurse into any\n“list-like” element. Set `classes = \"list\"` in `rrapply()` to override\nand apply `f` to any list element (i.e. a sublist) that satisfies the\n`condition` argument. This can be useful to e.g. collapse sublists or\ncalculate summary statistics across elements in a nested list:\n\n``` r\n## calculate mean value of Europe\nrrapply(\n  renewable_energy_by_country,  \n  condition = \\(x, .xname) .xname == \"Europe\",\n  f = \\(x) mean(unlist(x), na.rm = TRUE),\n  classes = \"list\",\n  how = \"flatten\"\n)\n\n#\u003e   Europe \n#\u003e 22.36565\n\n## calculate mean value for each continent\n## (Antartica's value is missing)\nrrapply(\n  renewable_energy_by_country, \n  condition = \\(x, .xpos) length(.xpos) == 2,\n  f = \\(x) mean(unlist(x), na.rm = TRUE),\n  classes = \"list\"\n) |\u003e\n  str(give.attr = FALSE)\n\n#\u003e List of 1\n#\u003e  $ World:List of 6\n#\u003e   ..$ Africa    : num 54.3\n#\u003e   ..$ Americas  : num 18.2\n#\u003e   ..$ Antarctica: logi NA\n#\u003e   ..$ Asia      : num 17.9\n#\u003e   ..$ Europe    : num 22.4\n#\u003e   ..$ Oceania   : num 17.8\n\n## simplify pokemon evolutions to character vectors \nrrapply(\n  pokedex,\n  condition = \\(x, .xname) .xname %in% c(\"name\", \"next_evolution\", \"prev_evolution\"), \n  f = \\(x) if(is.list(x)) sapply(x, `[[`, \"name\") else x,\n  classes = c(\"character\", \"list\"),\n  how = \"bind\"\n) |\u003e\n  head(n = 9)\n\n#\u003e         name        next_evolution         prev_evolution\n#\u003e 1  Bulbasaur     Ivysaur, Venusaur                     NA\n#\u003e 2    Ivysaur              Venusaur              Bulbasaur\n#\u003e 3   Venusaur                    NA     Bulbasaur, Ivysaur\n#\u003e 4 Charmander Charmeleon, Charizard                     NA\n#\u003e 5 Charmeleon             Charizard             Charmander\n#\u003e 6  Charizard                    NA Charmander, Charmeleon\n#\u003e 7   Squirtle  Wartortle, Blastoise                     NA\n#\u003e 8  Wartortle             Blastoise               Squirtle\n#\u003e 9  Blastoise                    NA    Squirtle, Wartortle\n```\n\n**Hint**: as data.frames are also list-like objects, `rrapply()` applies\n`f` to individual data.frame columns by default. Set\n`classes = \"data.frame\"` to avoid this behavior and apply the `f` and\n`condition` functions to complete data.frame objects instead of\nindividual data.frame columns.\n\n### Recursive list updating\n\n#### • `how = \"recurse\"`\n\nIf `classes = \"list\"` and `how = \"recurse\"`, `rrapply()` applies the `f`\nfunction to any list element that satisfies the `condition` argument\nsimilar to the previous section, but recurses further into any *updated*\nlist-like element after application of `f`. This can be useful to\ne.g. recursively update the class or other attributes of all elements in\na nested list:\n\n``` r\n## recursively remove all list attributes\nrrapply(\n  renewable_oceania,\n  f = \\(x) c(x),\n  classes = c(\"list\", \"ANY\"),\n  how = \"recurse\"\n) |\u003e\n  str(list.len = 3, give.attr = TRUE)\n\n#\u003e List of 1\n#\u003e  $ Oceania:List of 4\n#\u003e   ..$ Australia and New Zealand:List of 6\n#\u003e   .. ..$ Australia                        : num 9.32\n#\u003e   .. ..$ Christmas Island                 : logi NA\n#\u003e   .. ..$ Cocos (Keeling) Islands          : logi NA\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ Melanesia                :List of 5\n#\u003e   .. ..$ Fiji            : num 24.4\n#\u003e   .. ..$ New Caledonia   : num 4.03\n#\u003e   .. ..$ Papua New Guinea: num 50.3\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ Micronesia               :List of 8\n#\u003e   .. ..$ Guam                                : num 3.03\n#\u003e   .. ..$ Kiribati                            : num 45.4\n#\u003e   .. ..$ Marshall Islands                    : num 11.8\n#\u003e   .. .. [list output truncated]\n#\u003e   .. [list output truncated]\n```\n\n#### • `how = \"names\"`\n\nThe option `how = \"names\"` is a special case of `how = \"recurse\"`, where\nthe value of `f` is used to replace the *name* of the evaluated list\nelement instead of its *content* (as with all other `how` options). By\ndefault, `how = \"names\"` uses `classes = c(\"list\", \"ANY\")` in order to\nallow updating of all names in the nested list.\n\n``` r\n## recursively replace all names by M49-codes\nrrapply(\n  renewable_oceania,\n  f = \\(x) attr(x, \"M49-code\"),\n  how = \"names\"\n) |\u003e\n  str(list.len = 3, give.attr = FALSE)\n\n#\u003e List of 1\n#\u003e  $ 009:List of 4\n#\u003e   ..$ 053:List of 6\n#\u003e   .. ..$ 036: num 9.32\n#\u003e   .. ..$ 162: logi NA\n#\u003e   .. ..$ 166: logi NA\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ 054:List of 5\n#\u003e   .. ..$ 242: num 24.4\n#\u003e   .. ..$ 540: num 4.03\n#\u003e   .. ..$ 598: num 50.3\n#\u003e   .. .. [list output truncated]\n#\u003e   ..$ 057:List of 8\n#\u003e   .. ..$ 316: num 3.03\n#\u003e   .. ..$ 296: num 45.4\n#\u003e   .. ..$ 584: num 11.8\n#\u003e   .. .. [list output truncated]\n#\u003e   .. [list output truncated]\n```\n\n### Expression objects\n\nBase `rapply()` does not include recursion for expression objects. In\ncontrast `rrapply()` supports recursion of call objects and expression\nvectors, which are treated as nested lists based on their abstract\nsyntax trees. As such, all functionality that applies to nested lists\nextends directly to call objects and expression vectors.\n\nTo update the abstract syntax tree of a call object, use\n`how = \"replace\"`:\n\n``` r\n## language object\n(lang \u003c- quote(y \u003c- x \u003c- 1 + TRUE))\n\n#\u003e y \u003c- x \u003c- 1 + TRUE\n\n## replace logicals by integers \nrrapply(lang, classes = \"logical\", f = as.numeric, how = \"replace\")\n\n#\u003e y \u003c- x \u003c- 1 + 1\n```\n\nTo update the abstract syntax tree and return it as a nested list, use\n`how = \"list\"`:\n\n``` r\n## update and decompose call object\nrrapply(lang, f = function(x) ifelse(is.logical(x), as.numeric(x), x), how = \"list\") |\u003e\n  str()\n\n#\u003e List of 3\n#\u003e  $ : symbol \u003c-\n#\u003e  $ : symbol y\n#\u003e  $ :List of 3\n#\u003e   ..$ : symbol \u003c-\n#\u003e   ..$ : symbol x\n#\u003e   ..$ :List of 3\n#\u003e   .. ..$ : symbol +\n#\u003e   .. ..$ : num 1\n#\u003e   .. ..$ : num 1\n```\n\nThe modes `how = \"prune\"`, `how = \"flatten\"` and `how = \"melt\"` return\nthe pruned abstract syntax tree as: a nested list, a flattened list and\na melted data.frame respectively. This is identical to application of\n`rrapply()` to the abstract syntax tree formatted as a nested list.\n\nTo illustrate, we return all names (i.e. symbols) in the abstract syntax\ntree that not part of base R:\n\n``` r\n## expression vector\nexpr \u003c- expression(y \u003c- x \u003c- 1, f(g(2 * pi)))\nis_new_name \u003c- function(x) !exists(as.character(x), envir = baseenv())\n\n## prune and decompose expression\nrrapply(expr, classes = \"name\", condition = is_new_name, how = \"prune\") |\u003e\n  str()\n\n#\u003e List of 2\n#\u003e  $ :List of 2\n#\u003e   ..$ : symbol y\n#\u003e   ..$ :List of 1\n#\u003e   .. ..$ : symbol x\n#\u003e  $ :List of 2\n#\u003e   ..$ : symbol f\n#\u003e   ..$ :List of 1\n#\u003e   .. ..$ : symbol g\n\n## prune and flatten expression\nrrapply(expr, classes = \"name\", condition = is_new_name, how = \"flatten\") |\u003e\n  str()\n\n#\u003e List of 4\n#\u003e  $ : symbol y\n#\u003e  $ : symbol x\n#\u003e  $ : symbol f\n#\u003e  $ : symbol g\n\n## prune and melt expression\nrrapply(expr, classes = \"name\", condition = is_new_name, f = as.character, how = \"melt\")\n\n#\u003e   L1 L2   L3 value\n#\u003e 1  1  2 \u003cNA\u003e     y\n#\u003e 2  1  3    2     x\n#\u003e 3  2  1 \u003cNA\u003e     f\n#\u003e 4  2  2    1     g\n```\n\nFor more details and examples on how to use the `rrapply()` function see\nthe accompanying package vignette in the vignettes folder or the\nArticles section at \u003chttps://jorischau.github.io/rrapply/\u003e.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjorischau%2Frrapply","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjorischau%2Frrapply","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjorischau%2Frrapply/lists"}