{"id":13712770,"url":"https://github.com/stefanedwards/lemon","last_synced_at":"2026-02-22T10:36:19.130Z","repository":{"id":56936255,"uuid":"89286206","full_name":"stefanedwards/lemon","owner":"stefanedwards","description":"🍋 Lemon --- Freshing up your ggplots","archived":false,"fork":false,"pushed_at":"2024-11-13T08:12:48.000Z","size":896,"stargazers_count":189,"open_issues_count":6,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-16T20:15:54.704Z","etag":null,"topics":["axis-lines","facets","ggplot-extension","ggplot2","knitr","legend","ticks","visualization"],"latest_commit_sha":null,"homepage":"https://cran.r-project.org/package=lemon","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stefanedwards.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2017-04-24T20:54:19.000Z","updated_at":"2025-03-22T08:14:28.000Z","dependencies_parsed_at":"2023-01-24T05:31:03.830Z","dependency_job_id":"94554810-09a6-4f1c-b4a2-d52786ae12e4","html_url":"https://github.com/stefanedwards/lemon","commit_stats":{"total_commits":162,"total_committers":6,"mean_commits":27.0,"dds":"0.26543209876543206","last_synced_commit":"6e01b61f4e10774684707ffde7ad31fd8a6d61bf"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanedwards%2Flemon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanedwards%2Flemon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanedwards%2Flemon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanedwards%2Flemon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stefanedwards","download_url":"https://codeload.github.com/stefanedwards/lemon/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252779070,"owners_count":21802876,"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":["axis-lines","facets","ggplot-extension","ggplot2","knitr","legend","ticks","visualization"],"created_at":"2024-08-02T23:01:22.437Z","updated_at":"2025-10-21T19:25:51.740Z","avatar_url":"https://github.com/stefanedwards.png","language":"R","funding_links":[],"categories":["Themes and aesthetics","R"],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, echo = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"README/\",\n  cache.path = \"README/cache/\",\n  cache = TRUE,\n  autodep=TRUE,\n  cache.rebuild = TRUE\n)\n```\n\n# Lemon --- Freshing up your ggplots\n\n[![CRAN\\_Status\\_Badge](https://www.r-pkg.org/badges/version/lemon)](https://cran.r-project.org/package=lemon)\n![downloads](http://cranlogs.r-pkg.org/badges/grand-total/lemon)\n\u003c!-- badges: start --\u003e\n  [![R-CMD-check](https://github.com/stefanedwards/lemon/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/stefanedwards/lemon/actions/workflows/R-CMD-check.yaml)\n  \u003c!-- badges: end --\u003e\n\nJust another [ggplot2](http://ggplot2.tidyverse.org) and \n[knitr](https://yihui.name/knitr/) extension package.\n\nThis package contains functions primarily in these domains of ggplot2:\n\n```{r domain_axis_lines,include=FALSE,fig.height=0.5,fig.width=0.5}\nlibrary(ggplot2)\nlibrary(lemon)\nggplot(mtcars, aes(x=cyl, y=mpg)) + \n  geom_point(size=0.1) + \n  coord_capped_cart(bottom=brackets_horisontal(), left='both') +\n  theme_light() + \n  theme(panel.border=element_blank(), axis.line = element_line(),\n        axis.title=element_blank(), axis.text=element_blank(),\n        panel.grid=element_blank(), axis.ticks.x = element_line(colour='black'))\n```\n```{r domain_facets,include=FALSE,fig.height=0.5, fig.width=0.5}\nggplot(mtcars, aes(x=cyl, y=mpg)) + \n  geom_point(size=0.1) + \n  coord_capped_cart(bottom='both', left='both') +\n  facet_rep_wrap(~carb) +\n  theme_light() + \n  theme(panel.border=element_blank(), axis.line = element_line(),\n        axis.title=element_blank(), axis.text=element_blank(),\n        panel.grid=element_blank(), axis.ticks = element_blank(), \n        axis.ticks.length = unit(0, 'npc'), panel.spacing=unit(1, 'mm'),\n        strip.background=element_blank(), strip.text=element_blank())\n```\n```{r domain_pointline,include=FALSE,fig.height=0.5,fig.width=0.5}\nggplot(data.frame(x=1:3, y=c(1,2.4,3.5)), aes(x, y)) +\n  geom_pointline(size=0.5) +\n  coord_capped_cart(xlim=c(0,4), bottom='both', left='both') +\n  theme_light() + \n  theme(panel.border=element_blank(), axis.line = element_line(),\n        axis.title=element_blank(), axis.text=element_blank(),\n        panel.grid=element_blank(), axis.ticks.x = element_line(colour='black'))\n```\n\n-   ![Axis lines miniature](README/domain_axis_lines-1.png) Axis lines.\n-   ![Facets miniature](README/domain_facets-1.png) Repeated axis lines on facets.\n-   ![geom_pointline](README/domain_pointline-1.png) `geom_pointpath` and `geom_pointline`.\n-   Legends\n\nAs well as some functions in knitr.\n\n## Installation\n\n```{r, eval = FALSE}\n# install.packages(\"devtools\")\n\n# Install release from GitHub:\ndevtools::install_github(\"stefanedwards/lemon\", ref='v0.4.7')\n\n# Or get the lastest development version from GitHub:\ndevtools::install_github(\"stefanedwards/lemon\")\n```\n\n\n\n## Axis lines\n\nWe can display a limit on the axes range.\n```{r usage1}\nlibrary(lemon)\nggplot(mtcars, aes(x=cyl, y=mpg)) + \n  geom_point() + \n  coord_capped_cart(bottom='both', left='none') +\n  theme_light() + theme(panel.border=element_blank(), axis.line = element_line())\n```\n\n**NB**: Disable `panel.border` and enable `axis.line` in `theme`, otherwise you will not see an effect!\n\nWe could also show that the x-axis is categorical (or ordinal):\n```{r brackets_demo}\n(p \u003c- ggplot(mtcars, aes(x=as.factor(cyl), y=mpg)) + \n  geom_point(position=position_jitter(width=0.1)) + \n  coord_flex_cart(bottom=brackets_horisontal(), left=capped_vertical('both')) +\n  theme_light() + theme(panel.border=element_blank(), axis.line = element_line())\n)\n```\n\nWhen capping the axis lines, they are never capped further inwards than the ticks!\nLook up\n\n* `coord_capped_cart`, `coord_capped_flip`\n* `coord_flex_cart`, `coord_flex_flip`, `coord_flex_fixed`\n* `brackets_horisontal`, `brackets_vertical`\n* `capped_horisontal`, `capped_vertical`\n\n## Facets \n\nHaving produced such wonderous axes, it is a pity they are not plotted around \nall panels when using faceting. \nWe have extended both `facet_grid` and `facet_wrap` to produce axis, ticks, and \nlabels on _all_ panels:\n\n```{r facets}\np + facet_rep_wrap(~gear, ncol=2, label=label_both)\n```\n\nThey work just like the normal ones; look up `facet_rep_grid` and `facet_rep_wrap`.\n\n## `geom_pointline`\n\nA geom that combines both points and lines. \nWhile possible by using both `geom_point` and `geom_line`, position adjustments\nare not preserved between the two layers.\n`geom_pointline` and `geom_pointpath` combines `geom_point` with \n`geom_line` and `geom_path`, respectively, while preserving position adjustments.\n\n\n```{r geom_pointline_demo,echo=FALSE}\nlibrary(grid)\nlibrary(gtable)\n\np \u003c- ggplot(mtcars, aes(wt, mpg, colour=factor(cyl))) + \n  geom_point(col='grey') +\n  theme_light() + theme(panel.border=element_blank(), axis.line = element_line()) +\n  theme(legend.position='hidden', plot.title = element_text(size=rel(0.8)))\n\np1 \u003c- p + geom_point(position=position_jitter(0.1, 0.1)) + geom_line(position=position_jitter(0.1, 0.1)) +\n  labs(title='geom_point(position=position_jitter(0.1, 0.1)) + \\ngeom_line(position=position_jitter(0.1, 0.1))')\np2 \u003c- p + geom_pointline(position=position_jitter(0.1, 0.1)) +\n  labs(title='geom_pointline(position=position_jitter(0.1, 0.1))')\n\ng1 \u003c- ggplotGrob(p1)\ng2 \u003c- ggplotGrob(p2)\ngrid.newpage()\ngrid.draw(cbind(g1, g2, size = 'first'))\n```\nLeft: `geom_point` and `geom_line` as two separate geoms. \nRight: The two geoms combined into `geom_pointline`. \nBoth produced with `ggplot(mtcars, aes(wt, mpg, colour=factor(cyl))) + geom_point(col='grey')`, where the grey points indicate the true location of the datapoint.\n\nAn added visual effect is seen as the lines do not touch the points, leaving a \nsmall gap (set by argument `distance`).\n\n## Legends\n\nReposition the legend onto the plot. Exactly where you want it:\n```{r reposition_legend}\ndsamp \u003c- diamonds[sample(nrow(diamonds), 1000), ]\nd \u003c- ggplot(dsamp, aes(carat, price)) +\n  geom_point(aes(colour = clarity))\nreposition_legend(d, 'top left')\n```\nThe legend repositioned onto the top left corner of the panel.\n\nScavenging the Internet, we have found some functions that help work with \nlegends.\n\nFrequently appearing on [Stack Overflow](https://stackoverflow.com), we bring \nyou `g_legend`:\n```{r g_legend,fig.height=3,fig.width=2}\nlibrary(grid)\nlegend \u003c- g_legend(d)\ngrid.newpage()\ngrid.draw(legend)\n```\nThe legend grob, by itself.\n\n\nOriginally brought to you by\n  (Baptiste Auguié)[http://baptiste.github.io/]\n  (\u003chttps://github.com/tidyverse/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs\u003e)\n  and \n  (Shaun Jackman)[http://rpubs.com/sjackman]\n  (\u003chttp://rpubs.com/sjackman/grid_arrange_shared_legend\u003e).\nWe put it in a package.\n\n```{r grid_arrange_shared_legend}\ndsamp \u003c- diamonds[sample(nrow(diamonds), 1000), ]\np1 \u003c- qplot(carat, price, data = dsamp, colour = clarity)\np2 \u003c- qplot(cut, price, data = dsamp, colour = clarity)\np3 \u003c- qplot(color, price, data = dsamp, colour = clarity)\np4 \u003c- qplot(depth, price, data = dsamp, colour = clarity)\ngrid_arrange_shared_legend(p1, p2, p3, p4, ncol = 2, nrow = 2)\n```\nFour plots that share the same legend.\n\n## Extensions to knitr\n\n`knitr` allows S3 methods for `knit_print` for specialised printing of objects.\nWe provide `lemon_print` for data frames, dplyr tables, and summary objects, \nthat can  be used to render the output, without mucking up the code source.\nAn added benefit is that we can use RStudio's inline data frame viewer:\n\n![Viewing data frames in R Notebooks in RStudio](vignettes/lemon_print_capture.png)\n\n\n### Relative file paths made safe\n\nUsing `knitr` for computations that use external binaries and/or write temporary\nfiles, setting the root directory for `knitr`'s knitting saves the user from a\nfile mess. E.g.\n\n```r\nknitr::opts_knit$set(root.dir=TMPDIR)\n```\n\nBut we want to keep our file paths relative for the scripts / document to be \ntransferable. We introduce the `.dot` functions:\n\n```r\nTMPDIR=tempdir()\n\n.data \u003c- .dot('data')\n\nknitr_opts_knit$set(root.dir=TMPDIR)\n```\n\nWe can then load our data file using the created `.data` function,\neven though the chunk is executed from TMPDIR.\n\n```r\ndat \u003c- read.table(.data('mydata.tab'))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstefanedwards%2Flemon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstefanedwards%2Flemon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstefanedwards%2Flemon/lists"}