diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..dd631b3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,83 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this is + +Jacob Dawang's personal website and blog at [jacobdawang.com](https://www.jacobdawang.com), built with [Quarto](https://quarto.org/). Blog posts are data analysis pieces focused on Edmonton housing, zoning, and transit, written in R using Quarto documents (`.qmd`). + +## Build commands + +```bash +# Preview site locally (live reload) +quarto preview + +# Render the full site +quarto render +``` + +Always render a single post from within the post's directory. This allows for the post to be rendered within its own environment. For example: +```bash +# Render a single post (from post directory) +cd blog/2026/nodes-corridors +quarto render blog/2026/nodes-corridors/index.qmd +``` + +Deployment is automatic via GitHub Actions on push to `main`: renders with Quarto and deploys to Cloudflare Pages. Deployment to a preview url is automatic via GitHub actions on pushes to open pull requests. + +## Architecture + +- **`_quarto.yml`**: Site-level config (theme, navbar, footer, extensions). `freeze: true` means computed R outputs are cached in `_freeze/` and not re-executed unless the source changes. +- **`blog/_metadata.yml`**: Defaults for all blog posts (freeze, echo/message/warning suppression, giscus comments, title-block-banner). +- **`_freeze/`**: Cached execution results (JSON + figures). Committed to the repo so CI doesn't need R packages installed. +- **`_site/`**: Build output, committed to repo. +- **`_extensions/`**: Quarto extensions (fontawesome, iconify, social-embeds). +- **`custom_styles.scss` / `custom_styles_dark.scss`**: Theme overrides for light/dark modes on top of the cosmo Bootstrap theme. +- **`data/`**: Shared datasets (geojson, csv, zip) referenced across blog posts. + +## Blog post structure + +Each post lives at `blog/YYYY/post-slug/index.qmd`. The frontmatter pattern: + +```yaml +--- +title: "Post title" +date: "YYYY-MM-DD" +author: "Jacob Dawang" +categories: [category1, category2, category3] +description: "few sentence summary" +link-external-newwindow: true +link-external-icon: false +--- +``` + +Posts use R code chunks with knitr. Common libraries: `tidyverse`, `sf`, `gt`, `ggplot2`, `cancensus`, `mountainmathHelpers`. Data paths typically reference `../../../data` relative to the post via `here()`. + +## R package management + +Posts have their own `renv.lock` for reproducibility. To restore packages for a specific post: + +```bash +cd blog/2026/nodes-corridors +Rscript -e "renv::restore()" +``` + +When creating a new post, always: + +- Initialize renv in its directory using `renv::init()`. +- Install required packages before trying to execute code. + +If you come across an error like "[package name or function name] not found", that is most likely due to not installing the package. Install it and try again. + +Before committing changes to a blog post, always run `renv::snapshot()` from within its directory to ensure the environment is saved. + +## Freeze behaviour + +Because `freeze: true` is set globally, rendered outputs are stored in `_freeze/` and reused. To force re-execution of a post's R code, change into the post's directory and rerender it with the `--no-freeze` option. + +```bash +cd blog/2026/nodes-corridors/ +quarto render blog/2026/nodes-corridors/index.qmd --no-freeze +``` + +The `blog/2022/election-maps-2022/index.qmd` is explicitly excluded from rendering in `_quarto.yml`. diff --git a/Containerfile b/Containerfile index a93d94b..8890092 100644 --- a/Containerfile +++ b/Containerfile @@ -1,17 +1,17 @@ FROM ghcr.io/rocker-org/geospatial:4.5.2 -RUN sudo curl -sLO https://cdn.posit.co/positron/releases/deb/x86_64/Positron-2026.01.0-147-x64.deb \ +RUN sudo curl -sLO https://cdn.posit.co/positron/releases/deb/x86_64/Positron-2026.03.0-212-x64.deb \ && sudo curl -L https://rig.r-pkg.org/deb/rig.gpg -o /etc/apt/trusted.gpg.d/rig.gpg \ && sudo sh -c 'echo "deb http://rig.r-pkg.org/deb rig main" > /etc/apt/sources.list.d/rig.list' \ && sudo apt-get update \ - && sudo apt install -y ./Positron-2026.01.0-147-x64.deb \ + && sudo apt install -y ./Positron-2026.03.0-212-x64.deb \ && sudo apt install -y \ - bat \ - fonts-firacode \ - r-rig \ - zsh \ - cargo \ - rustc \ + bat \ + fonts-firacode \ + r-rig \ + zsh \ + cargo \ + rustc \ && sudo curl -sS https://starship.rs/install.sh | sh -s -- -y \ && chsh -s $(which zsh) \ && rig add 4.5.2 diff --git a/_freeze/blog/2026/property-values/index/execute-results/html.json b/_freeze/blog/2026/property-values/index/execute-results/html.json new file mode 100644 index 0000000..a37fd69 --- /dev/null +++ b/_freeze/blog/2026/property-values/index/execute-results/html.json @@ -0,0 +1,15 @@ +{ + "hash": "ed2d48fafd528a34d115def0f47926e6", + "result": { + "engine": "knitr", + "markdown": "---\ntitle: \"Infill construction and property values in Edmonton\"\ndate: \"2026-03-08\"\nauthor: \"Jacob Dawang\"\ncategories: [housing, edmonton, zoning, property value]\ndescription: \"Using a first-difference event study design, I find no evidence that nearby multi-unit infill construction reduces property appreciation rates in Edmonton's mature neighbourhoods — and some evidence it slightly accelerates them.\"\nlink-external-newwindow: true\nlink-external-icon: false\n---\n\nIn a [previous post](../../2025/property-value-preliminary/), I showed some descriptive evidence that properties near new multi-unit buildings don't appreciate less than properties farther away. That analysis was intentionally preliminary: comparing group medians year-by-year doesn't account for the fact that infill tends to cluster in specific neighbourhoods, on specific lot types, and near properties that may already be on different value trajectories.\n\nThis post applies more rigorous methods to the same question. Using a first-difference event study design, I control for all time-invariant differences across properties (location, lot size, age, neighbourhood character) and for city-wide appreciation trends.\n\nThe answer is the same as the preliminary post: **there is no evidence that multi-unit infill construction reduces nearby property values**, across every specification.\n\n## Data\n\nAll data are from Edmonton's open data portal.\n\n- **Historical property assessment data**, 2015–2024. I filter for residential properties (`mill_class_1 == \"RESIDENTIAL\"`) with positive assessed values.\n- **General building permit data**, 2009–2025. Filtered using the same criteria as the preliminary post: permits adding ≥1 unit, excluding excavation-only permits.\n- **Mature neighbourhood boundaries** (2024 vintage).\n\nThe treatment variable follows the preliminary post: a **multi-unit building permit** is one for ≥6 units, excluding new single-family homes, backyard houses, additions/conversions, and duplex-to-fourplex permits. A property is *treated* in assessment year $t$ if such a permit was issued within 50m in year $t - 1$, giving time for the building's presence to be reflected in assessed value.\n\nThe sample is restricted to mature neighbourhoods (excluding Downtown), where infill has been most active.\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n\n::: {.cell}\n\n:::\n\n\n## Methods\n\nThe preliminary post compared median property value changes between a \"treated\" group (nearby multi-unit permit) and a \"control\" group. The limitation is that treated and control properties may differ systematically: infill tends to cluster in specific neighbourhoods, on certain street types, and near properties that may already be on different value trajectories.\n\nA first-difference (FD) approach addresses this by using each property's *year-over-year change in log assessed value* as the outcome. Time-invariant differences between properties — location, lot size, year built — cancel out in differencing, because they affect value levels equally in every year. A neighbourhood × year fixed effect absorbs both city-wide appreciation trends and neighbourhood-specific appreciation dynamics, comparing treated and control properties *within the same neighbourhood in the same year*. This removes bias from infill clustering in already-appreciating areas. The parallel trends assumption is weaker than in a levels regression: it requires only that treated and control properties within the same neighbourhood would have appreciated at similar *rates* absent treatment, not that they were on parallel value *levels*.\n\nThe event study estimates separate effects at each point in time relative to the first nearby permit: $t = -4, -3, -2, -1$ (pre-treatment), and $t = 0, +1, +2, +3, +4$ (post-treatment). If the parallel trends assumption holds — i.e., treated and control properties in the same neighbourhood would have followed similar appreciation rate trajectories absent treatment — the pre-treatment coefficients should be near zero. Flat pre-trends are not proof of causality, but they are necessary evidence for it.\n\nI use the Sun-Abraham (2021) estimator (`sunab()` in the `fixest` package), which is robust to heterogeneous treatment effects across cohorts — important here because properties receive their first nearby permit in different years throughout 2015–2024.\n\n## Results\n\nEach analysis below is shown for two samples side by side. The **all residential** sample covers all residential properties in mature neighbourhoods. The **always-SFH** sample excludes any property that ever had a ≥6-unit permit issued within 10m of itself during the study period — removing properties approaching redevelopment, which tend to be assessed near land value and cluster near new infill. The always-SFH sample most directly answers the policy question: *does building apartments next door hurt my house's value?*\n\n\n\n::: {#tbl-fd .cell tbl-cap='First-difference estimates: effect of nearby multi-unit permit on year-over-year log assessed value change. All models use neighbourhood × year fixed effects.'}\n::: {.cell-output-display}\n\n```{=html}\n\n\n \n\n \n\n \n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
All residential\n(≥6 units)Always-SFH\n(≥6 units)All residential\n(≥2 units)Always-SFH\n(≥2 units)
Standard errors clustered by property. 95% confidence intervals in brackets.
Multi-unit permit within 50m (≥6 units)0.01182.053e-04
[0.0049, 0.0188][-0.0031, 0.0035]
Multi-unit permit within 50m (≥2 units)0.03740.0369
[0.0340, 0.0409][0.0335, 0.0404]
Observations1,144,5371,134,5611,144,5371,134,561
Neighbourhood × year FEXXXX
\n
\n\n```\n\n:::\n:::\n\n\nThe always-SFH estimates (both thresholds) are near zero — consistent with no effect on stable single-family homes. The all-residential estimates are near zero or slightly positive: properties near new multi-unit permits appreciate at similar or slightly faster rates on average, not slower. The ≥2-unit columns show that the null result holds for smaller infill types (including duplex-to-fourplex), not just large apartment buildings.\n\nThe first-difference event studies (@fig-es-fd-main and @fig-es-fd-sfh) test whether appreciation *rates* were diverging before treatment. The always-SFH pre-trends are flat, and post-treatment estimates are near zero throughout — a clean null result. The all-residential event study tells a more revealing story: there is a large positive spike at $t = 0$, which then reverts to near zero. This spike is almost certainly driven by properties approaching redevelopment in the all-residential sample: when a multi-unit permit appears nearby, properties that are themselves candidates for demolition see an immediate reassessment of their land value. The always-SFH exclusion removes this effect entirely, confirming that stable single-family homes see no change in appreciation rates. See @tbl-es-fd-sample for treated-observation counts by cohort and relative year.\n\n\n::: {.cell}\n::: {.cell-output-display}\n![First-difference event study: all residential properties](index_files/figure-html/fig-es-fd-main-1.png){#fig-es-fd-main width=672}\n:::\n:::\n\n\n\n::: {.cell}\n::: {.cell-output-display}\n![First-difference event study: always-SFH properties](index_files/figure-html/fig-es-fd-sfh-1.png){#fig-es-fd-sfh width=672}\n:::\n:::\n\n\n\n::: {#tbl-es-fd-sample .cell tbl-cap='First-difference event study: treated observations per cohort and relative year'}\n::: {.cell-output-display}\n\n```{=html}\n
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n
Cohort\n
Pre-treatment (relative year)
\n
\n
Post-treatment (relative year)
\n
-8-7-6-5-4-3-2-10+1+2+3+4+5+6+7+8
All residential
20159595959595959595
2016313131313131313131
20175540404040404040
2018141414212121212121
2019999999999
2020242424252727272727
2021123123124124127127127127127
2022137138138141141143143153153
2023293298302304306310311313319
2024356357367368375379385387387
Always-SFH
20152323232323232323
2016313131313131313131
2017555555555
2018141414141414141414
2019999999999
2020232323242626262626
2021120120121121124124124124124
2022134135135137137139139139139
2023275280284286288292295295297
2024307308317318325329335335335
\n
\n```\n\n:::\n:::\n\n\n@fig-es-fd-sfh-robust repeats the always-SFH FD event study restricted to cohorts 2017 and later — the earliest cohort with at least one pre-treatment FD observation. The result is unchanged: all estimates are statistically indistinguishable from zero throughout the full time horizon, with no systematic trend.\n\n\n::: {.cell}\n::: {.cell-output-display}\n![First-difference event study: always-SFH, cohorts 2017 and later only (cohorts 2015–2016 excluded — no pre-treatment data in FD sample)](index_files/figure-html/fig-es-fd-sfh-robust-1.png){#fig-es-fd-sfh-robust width=672}\n:::\n:::\n\n\n\n## Caveats\n\n**Parallel trends is untestable.** Flat pre-trends are necessary but not sufficient evidence for a causal interpretation. A time-varying confounder that begins exactly when the permit is issued — say, a developer specifically targeting blocks that are about to appreciate for unrelated reasons — could still bias the estimates. The flat pre-trends make this story less plausible, but it cannot be ruled out.\n\n**Developer selection likely biases toward finding a positive effect.** If developers preferentially site multi-unit builds near properties that are already appreciating (e.g., near amenities, on major streets), the \"treated\" group would be expected to appreciate faster even without the infill. This would work against finding a null result, making the null finding more conservative, not less.\n\n**Assessed value is not sale price.** Edmonton's assessment data reflects the city's model of market value, not observed transactions. City-wide assessment methodology changes are absorbed by year fixed effects, but property-specific reassessment events are not. Using only properties where the same assessment method applies across all years would be a useful robustness check.\n\n**One-year lag.** The treatment indicator uses permits issued in year $t-1$ to predict assessments in year $t$. Construction timelines vary — larger buildings may take two or more years to complete — so some effects may be lagged further than the specification captures. The event study, which shows no effect even 4+ years post-permit, addresses this concern.\n\n**The always-SFH sample conditions on an endogenous outcome.** The always-SFH sample excludes properties that were themselves eventually redeveloped within 10m of a ≥6-unit permit during the study period. If infill pressure causes adjacent properties to sell and redevelop, this exclusion removes potentially affected properties. The always-SFH estimates should therefore be interpreted as the effect on properties that did not experience redevelopment pressure — a well-defined and policy-relevant group, but not a random subset. The bias direction is ambiguous but likely toward a more null result.\n\n## Conclusion\n\nUsing year-over-year appreciation as the outcome, there is no evidence that multi-unit infill construction reduces neighbouring property values in Edmonton's mature neighbourhoods. The always-SFH estimates are near zero across both the ≥6-unit and ≥2-unit thresholds, and the all-residential estimates are near zero or slightly positive. The event study shows flat pre-trends and no post-treatment decline for stable single-family homes across the full post-treatment window. The all-residential sample does show a large positive spike at $t = 0$, almost certainly driven by properties approaching redevelopment being reassessed at land value — but this is a selection artefact that disappears in the always-SFH sample, confirming that stable homes are unaffected. All specifications use neighbourhood × year fixed effects, comparing treated and control properties within the same neighbourhood and year.\n\nThis is consistent with the [preliminary post](../../2025/property-value-preliminary/) and with a growing literature finding that upzoning and infill construction do not harm existing homeowners. The fear that new apartments will hurt house prices is not supported by Edmonton's own data. It should not be a reason to restrict where housing can be built.", + "supporting": [], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-1.png new file mode 100644 index 0000000..0184821 Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-fd-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-fd-1.png new file mode 100644 index 0000000..4edbd46 Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-fd-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-fd-sfh-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-fd-sfh-1.png new file mode 100644 index 0000000..e7abd83 Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-fd-sfh-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-sfh-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-sfh-1.png new file mode 100644 index 0000000..89bd7b1 Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-bands-sfh-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-dist-spline-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-spline-1.png new file mode 100644 index 0000000..cf7faef Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-spline-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-dist-spline-sfh-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-spline-sfh-1.png new file mode 100644 index 0000000..cf7faef Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-dist-spline-sfh-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-es-fd-main-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-es-fd-main-1.png new file mode 100644 index 0000000..3b51b57 Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-es-fd-main-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-es-fd-sfh-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-es-fd-sfh-1.png new file mode 100644 index 0000000..89ff0a2 Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-es-fd-sfh-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-es-fd-sfh-robust-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-es-fd-sfh-robust-1.png new file mode 100644 index 0000000..9c70d1a Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-es-fd-sfh-robust-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-es-main-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-es-main-1.png new file mode 100644 index 0000000..6986216 Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-es-main-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-es-sfh-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-es-sfh-1.png new file mode 100644 index 0000000..eb1bd1f Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-es-sfh-1.png differ diff --git a/_freeze/blog/2026/property-values/index/figure-html/fig-es-sfh-robust-1.png b/_freeze/blog/2026/property-values/index/figure-html/fig-es-sfh-robust-1.png new file mode 100644 index 0000000..cef68fd Binary files /dev/null and b/_freeze/blog/2026/property-values/index/figure-html/fig-es-sfh-robust-1.png differ diff --git a/_quarto.yml b/_quarto.yml index ec779de..f20a268 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -7,9 +7,6 @@ project: - "blog/**/*.md" - "!blog/2022/election-maps-2022/index.qmd" - "!README.md" - - "!blog/2025/property-values/index.qmd" - - "!blog/2025/election/index.qmd" - - "!blog/2025/nodes-corridors-bp/index.qmd" execute: freeze: true diff --git a/blog/2025/property-value-preliminary/index.qmd b/blog/2025/property-value-preliminary/index.qmd index 2b37a24..1639475 100644 --- a/blog/2025/property-value-preliminary/index.qmd +++ b/blog/2025/property-value-preliminary/index.qmd @@ -217,4 +217,4 @@ prepped %>% ## Next up -While descriptive analysis is useful, I do plan on examining this question further using models which can control for the effect of neighbourhood, specific properties, and more. Meanwhile, on a surface level, it doesn't seem like infill has any effect on property values, positive or negative. +While descriptive analysis is useful, I do plan on examining this question further using models which can control for the effect of neighbourhood, specific properties, and more. Meanwhile, on a surface level, it doesn't seem like infill has any effect on property values, positive or negative. \ No newline at end of file diff --git a/blog/2026/property-values/.Rprofile b/blog/2026/property-values/.Rprofile new file mode 100644 index 0000000..81b960f --- /dev/null +++ b/blog/2026/property-values/.Rprofile @@ -0,0 +1 @@ +source("renv/activate.R") diff --git a/blog/2026/property-values/.gitignore b/blog/2026/property-values/.gitignore new file mode 100644 index 0000000..f398a4e --- /dev/null +++ b/blog/2026/property-values/.gitignore @@ -0,0 +1,7 @@ +.Rproj.user +.Rhistory +.RData +.Ruserdata + +/.quarto/ +data/ diff --git a/blog/2026/property-values/.here b/blog/2026/property-values/.here new file mode 100644 index 0000000..e69de29 diff --git a/blog/2026/property-values/index.qmd b/blog/2026/property-values/index.qmd new file mode 100644 index 0000000..bc63446 --- /dev/null +++ b/blog/2026/property-values/index.qmd @@ -0,0 +1,484 @@ +--- +title: "Infill construction and property values in Edmonton" +date: "2026-03-08" +author: "Jacob Dawang" +categories: [housing, edmonton, zoning, property value] +description: "Using a first-difference event study design, I find no evidence that nearby multi-unit infill construction reduces property appreciation rates in Edmonton's mature neighbourhoods — and some evidence it slightly accelerates them." +link-external-newwindow: true +link-external-icon: false +draft: true +--- + +In a [previous post](../../2025/property-value-preliminary/), I showed some descriptive evidence that properties near new multi-unit buildings don't appreciate less than properties farther away. That analysis was intentionally preliminary: comparing group medians year-by-year doesn't account for the fact that infill tends to cluster in specific neighbourhoods, on specific lot types, and near properties that may already be on different value trajectories. + +This post applies more rigorous methods to the same question. Using a first-difference event study design, I control for all time-invariant differences across properties (location, lot size, age, neighbourhood character) and for city-wide appreciation trends. + +The answer is the same as the preliminary post: **there is no evidence that multi-unit infill construction reduces nearby property values**, across every specification. + +## Data + +All data are from Edmonton's open data portal. + +- **Historical property assessment data**, 2015–2024. I filter for residential properties (`mill_class_1 == "RESIDENTIAL"`) with positive assessed values. +- **General building permit data**, 2009–2025. Filtered using the same criteria as the preliminary post: permits adding ≥1 unit, excluding excavation-only permits. +- **Mature neighbourhood boundaries** (2024 vintage). + +The treatment variable follows the preliminary post: a **multi-unit building permit** is one for ≥6 units, excluding new single-family homes, backyard houses, additions/conversions, and duplex-to-fourplex permits. A property is *treated* in assessment year $t$ if such a permit was issued within 50m in year $t - 1$, giving time for the building's presence to be reflected in assessed value. + +The sample is restricted to mature neighbourhoods (excluding Downtown), where infill has been most active. + +```{r} +#| label: libraries +#| message: false +#| cache: false + +library(tidyverse) +library(sf) +library(gt) +library(fixest) +library(splines) +library(marginaleffects) +library(modelsummary) +library(mountainmathHelpers) +library(here) +``` + +```{r} +#| label: data +data_dir <- here("../../../data") + +historical <- read_rds(here(data_dir, "assessment_historical.rds")) %>% + filter(mill_class_1 == "RESIDENTIAL", assessed_value > 0) + +crs <- lambert_conformal_conic_at(historical) + +historical <- st_transform(historical, crs) + +mature_neighbourhood <- read_sf(here( + data_dir, + "Mature Neighbourhoods_20241222.geojson" +)) %>% + rename(neighbourhood = neighbourh) %>% + filter(neighbourhood != "Downtown") %>% + st_transform(crs) + +bp_raw <- read_sf(here(data_dir, "General Building Permits_20260113/")) %>% + rename( + construction_value = constructi, + month_number = month_numb, + building_type = building_t, + units_added = units_adde, + neighbourhood = neighbou_2, + job_category = job_catego, + job_description = job_descri, + date_issued = date_issue + ) %>% + filter(!st_is_empty(.)) %>% + st_transform(crs) + +bp <- bp_raw %>% + filter( + units_added >= 1, + building_type %in% + c( + "Apartment (310)", + "Apartment Condos (315)", + "Apartments (310)", + "Backyard House (110)", + "Duplex (210)", + "Garden Suite (110)", + "Mixed Use (522)", + "Row House (330)", + "Row House Condo (335)", + "Row House Condos (335)", + "Row Houses (330)", + "Semi-Detached Condo (215)", + "Semi-Detached House (210)", + "Single Detached Condo (115)", + "Single Detached House (110)" + ), + work_type != "(04) Excavation" + ) %>% + mutate( + project_type = fct( + case_when( + building_type %in% + c("Backyard House (110)", "Garden Suite (110)") ~ "Backyard House", + str_detect(work_type, coll("new", ignore_case = TRUE)) & + units_added == 1 ~ "New SFH", + work_type %in% + c( + "(03) Interior Alterations", + "(03) Exterior Alterations", + "(07) Add Suites to Single Dwelling", + "(08) Add Suites to Multi-Dwelling", + "(09) Convert Non-Res to Residential", + "(02) Addition", + "(12) Move Building on to Site" + ) ~ "Addition/Conversion", + between(units_added, 2, 4) ~ "Duplex to Fourplex", + between(units_added, 5, 8) ~ "Fiveplex to Eightplex", + str_detect( + building_type, + fixed("Row House", ignore_case = TRUE) + ) ~ "9+ Row House", + units_added >= 9 ~ "9+ Apartment", + .default = "Other" + ), + levels = c( + "New SFH", + "Addition/Conversion", + "Backyard House", + "Duplex to Fourplex", + "Fiveplex to Eightplex", + "9+ Row House", + "9+ Apartment", + "Other" + ) + ) + ) + +# Multi-unit permits: ≥6 units, not SFH/backyard/conversion/duplex-to-fourplex +bp_multi <- bp %>% + filter( + units_added >= 6, + !project_type %in% + c( + "New SFH", + "Backyard House", + "Addition/Conversion", + "Duplex to Fourplex" + ) + ) + +# Sensitivity: ≥2 units, not SFH/backyard/conversion (includes duplex-to-fourplex) +bp_multi_2plus <- bp %>% + filter( + units_added >= 2, + !project_type %in% + c( + "New SFH", + "Backyard House", + "Addition/Conversion" + ) + ) +``` + +```{r} +#| label: mature-and-redeveloped +# Properties in mature neighbourhoods (identified from 2024 geometries) +mature_accounts <- historical %>% + filter(assessment_year == 2024) %>% + st_filter(st_union(mature_neighbourhood)) %>% + pull(account_number) + +# "Ever redeveloped" indicator: properties within 10m of any ≥6-unit permit +# (the permit was issued on the property itself, not merely nearby) +# Use all permits from 2014 onward (study period + 1 year prior) +bp_multi_study <- bp_multi %>% filter(year >= 2014) + +assessment_2024 <- historical %>% filter(assessment_year == 2024) +redeveloped_flags <- st_is_within_distance( + assessment_2024, + bp_multi_study, + dist = units::as_units("10 m"), + sparse = TRUE +) +redeveloped_accounts <- assessment_2024$account_number[ + lengths(redeveloped_flags) > 0 +] +``` + +```{r} +#| label: merge-data +#| cache: true +years_included <- 2015:2024 +merged_fn <- here( + "data", + glue::glue("merged_v2_{min(years_included)}_{max(years_included)}.rds") +) +dir.create(here("data"), showWarnings = FALSE) + +if (!file.exists(merged_fn)) { + process_year <- function(y) { + bp_y <- bp_multi %>% filter(year == y - 1) + bp_2plus_y <- bp_multi_2plus %>% filter(year == y - 1) + assessment_y <- historical %>% filter(assessment_year == y) + + if (nrow(bp_y) == 0) { + units_multi_yn_col <- rep(0L, nrow(assessment_y)) + dist_col <- rep(NA_real_, nrow(assessment_y)) + units_permit_col <- rep(NA_real_, nrow(assessment_y)) + } else { + nearest_idx <- st_nearest_feature(assessment_y, bp_y) + nearest_dist <- as.numeric( + st_distance(assessment_y, bp_y[nearest_idx, ], by_element = TRUE) + ) + units_multi_yn_col <- as.integer(nearest_dist <= 50) + dist_col <- if_else(nearest_dist <= 500, nearest_dist, NA_real_) + units_permit_col <- if_else( + nearest_dist <= 50, + bp_y$units_added[nearest_idx], + NA_real_ + ) + } + + if (nrow(bp_2plus_y) == 0) { + units_multi_2plus_yn_col <- rep(0L, nrow(assessment_y)) + } else { + nearest_idx_2plus <- st_nearest_feature(assessment_y, bp_2plus_y) + nearest_dist_2plus <- as.numeric( + st_distance( + assessment_y, + bp_2plus_y[nearest_idx_2plus, ], + by_element = TRUE + ) + ) + units_multi_2plus_yn_col <- as.integer(nearest_dist_2plus <= 50) + } + + assessment_y %>% + st_drop_geometry() %>% + mutate( + units_multi_yn = units_multi_yn_col, + dist_nearest_multi = dist_col, + units_nearest_permit = units_permit_col, + units_multi_2plus_yn = units_multi_2plus_yn_col + ) + } + + merged <- map(years_included, process_year) %>% + list_rbind() %>% + group_by(account_number) %>% + arrange(assessment_year) %>% + mutate( + d_log_assessment = log(assessed_value) - lag(log(assessed_value)) + ) %>% + ungroup() %>% + write_rds(merged_fn) +} else { + merged <- read_rds(merged_fn) +} +``` + +```{r} +#| label: prep-data +prepped <- merged %>% + filter(account_number %in% mature_accounts) %>% + group_by(account_number) %>% + arrange(assessment_year) %>% + mutate( + units_multi_yn = replace_na(units_multi_yn, 0L), + units_multi_2plus_yn = replace_na(units_multi_2plus_yn, 0L), + first_year_treated = min( + if_else(units_multi_yn == 1L, assessment_year, Inf), + na.rm = TRUE + ), + rel_year = assessment_year - first_year_treated, + # Bin tails for event study display + rel_year_binned = pmax(pmin(rel_year, 4), -4) + ) %>% + ungroup() %>% + mutate( + ever_redeveloped = account_number %in% redeveloped_accounts + ) + +# "Always-SFH" subsample: never had a multi-unit permit issued on the property itself +prepped_sfh <- prepped %>% filter(!ever_redeveloped) +``` + +## Methods + +The preliminary post compared median property value changes between a "treated" group (nearby multi-unit permit) and a "control" group. The limitation is that treated and control properties may differ systematically: infill tends to cluster in specific neighbourhoods, on certain street types, and near properties that may already be on different value trajectories. + +A first-difference (FD) approach addresses this by using each property's *year-over-year change in log assessed value* as the outcome. Time-invariant differences between properties — location, lot size, year built — cancel out in differencing, because they affect value levels equally in every year. A neighbourhood × year fixed effect absorbs both city-wide appreciation trends and neighbourhood-specific appreciation dynamics, comparing treated and control properties *within the same neighbourhood in the same year*. This removes bias from infill clustering in already-appreciating areas. The parallel trends assumption is weaker than in a levels regression: it requires only that treated and control properties within the same neighbourhood would have appreciated at similar *rates* absent treatment, not that they were on parallel value *levels*. + +The event study estimates separate effects at each point in time relative to the first nearby permit: $t = -4, -3, -2, -1$ (pre-treatment), and $t = 0, +1, +2, +3, +4$ (post-treatment). If the parallel trends assumption holds — i.e., treated and control properties in the same neighbourhood would have followed similar appreciation rate trajectories absent treatment — the pre-treatment coefficients should be near zero. Flat pre-trends are not proof of causality, but they are necessary evidence for it. + +I use the Sun-Abraham (2021) estimator (`sunab()` in the `fixest` package), which is robust to heterogeneous treatment effects across cohorts — important here because properties receive their first nearby permit in different years throughout 2015–2024. + +## Results + +Each analysis below is shown for two samples side by side. The **all residential** sample covers all residential properties in mature neighbourhoods. The **always-SFH** sample excludes any property that ever had a ≥6-unit permit issued within 10m of itself during the study period — removing properties approaching redevelopment, which tend to be assessed near land value and cluster near new infill. The always-SFH sample most directly answers the policy question: *does building apartments next door hurt my house's value?* + + +```{r} +#| label: tbl-fd +#| tbl-cap: "First-difference estimates: effect of nearby multi-unit permit on year-over-year log assessed value change. All models use neighbourhood × year fixed effects." +m_fd_main <- feols( + d_log_assessment ~ units_multi_yn | neighbourhood_name^assessment_year, + data = prepped %>% filter(!is.na(d_log_assessment)), + cluster = ~account_number +) + +m_fd_sfh <- feols( + d_log_assessment ~ units_multi_yn | neighbourhood_name^assessment_year, + data = prepped_sfh %>% filter(!is.na(d_log_assessment)), + cluster = ~account_number +) + +m_fd_main_2plus <- feols( + d_log_assessment ~ units_multi_2plus_yn | neighbourhood_name^assessment_year, + data = prepped %>% filter(!is.na(d_log_assessment)), + cluster = ~account_number +) + +m_fd_sfh_2plus <- feols( + d_log_assessment ~ units_multi_2plus_yn | neighbourhood_name^assessment_year, + data = prepped_sfh %>% filter(!is.na(d_log_assessment)), + cluster = ~account_number +) + +modelsummary( + list( + "All residential\n(≥6 units)" = m_fd_main, + "Always-SFH\n(≥6 units)" = m_fd_sfh, + "All residential\n(≥2 units)" = m_fd_main_2plus, + "Always-SFH\n(≥2 units)" = m_fd_sfh_2plus + ), + coef_map = c( + "units_multi_yn" = "Multi-unit permit within 50m (≥6 units)", + "units_multi_2plus_yn" = "Multi-unit permit within 50m (≥2 units)" + ), + statistic = "conf.int", + conf_level = 0.95, + fmt = 4, + gof_map = list( + list(raw = "nobs", clean = "Observations", fmt = scales::label_comma()), + list( + raw = "FE: neighbourhood_name^assessment_year", + clean = "Neighbourhood × year FE", + fmt = NULL + ) + ), + notes = "Standard errors clustered by property. 95% confidence intervals in brackets." +) +``` + +The always-SFH estimates (both thresholds) are near zero — consistent with no effect on stable single-family homes. The all-residential estimates are near zero or slightly positive: properties near new multi-unit permits appreciate at similar or slightly faster rates on average, not slower. The ≥2-unit columns show that the null result holds for smaller infill types (including duplex-to-fourplex), not just large apartment buildings. + +The first-difference event studies (@fig-es-fd-main and @fig-es-fd-sfh) test whether appreciation *rates* were diverging before treatment. The always-SFH pre-trends are flat, and post-treatment estimates are near zero throughout — a clean null result. The all-residential event study tells a more revealing story: there is a large positive spike at $t = 0$, which then reverts to near zero. This spike is almost certainly driven by properties approaching redevelopment in the all-residential sample: when a multi-unit permit appears nearby, properties that are themselves candidates for demolition see an immediate reassessment of their land value. The always-SFH exclusion removes this effect entirely, confirming that stable single-family homes see no change in appreciation rates. See @tbl-es-fd-sample for treated-observation counts by cohort and relative year. + +```{r} +#| label: fig-es-fd-main +#| fig-cap: "First-difference event study: all residential properties" +es_fd_main <- feols( + d_log_assessment ~ sunab(first_year_treated, assessment_year) | + neighbourhood_name^assessment_year, + data = prepped %>% filter(!is.na(d_log_assessment)), + cluster = ~account_number +) + +iplot( + es_fd_main, + xlab = "Years relative to first nearby permit (≥6 units, within 50m)", + main = "", + ci_level = 0.95 +) +abline(v = -0.5, lty = 2, col = "grey50") +``` + +```{r} +#| label: fig-es-fd-sfh +#| fig-cap: "First-difference event study: always-SFH properties" +es_fd_sfh <- feols( + d_log_assessment ~ sunab(first_year_treated, assessment_year) | + neighbourhood_name^assessment_year, + data = prepped_sfh %>% filter(!is.na(d_log_assessment)), + cluster = ~account_number +) + +iplot( + es_fd_sfh, + xlab = "Years relative to first nearby permit (≥6 units, within 50m)", + main = "", + ci_level = 0.95 +) +abline(v = -0.5, lty = 2, col = "grey50") +``` + +```{r} +#| label: tbl-es-fd-sample +#| tbl-cap: "First-difference event study: treated observations per cohort and relative year" +ry_max <- 8L +ry_labs <- c(paste0("-", ry_max:1), "0", paste0("+", 1:ry_max)) + +make_es_counts <- function(data) { + data %>% + filter(is.finite(first_year_treated)) %>% + mutate( + cohort = as.integer(first_year_treated), + ry = as.integer(rel_year), + ry_lab = case_when( + ry > 0L ~ paste0("+", ry), + ry == 0L ~ "0", + TRUE ~ as.character(ry) + ) + ) %>% + filter(between(ry, -ry_max, ry_max)) %>% + count(cohort, ry_lab) %>% + pivot_wider(names_from = ry_lab, values_from = n, values_fill = 0L) %>% + select(cohort, any_of(ry_labs)) %>% + arrange(cohort) +} + +bind_rows( + make_es_counts(prepped %>% filter(!is.na(d_log_assessment))) %>% + mutate(sample = "All residential"), + make_es_counts(prepped_sfh %>% filter(!is.na(d_log_assessment))) %>% + mutate(sample = "Always-SFH") +) %>% + gt(groupname_col = "sample") %>% + cols_label(cohort = "Cohort") %>% + tab_spanner( + label = "Pre-treatment (relative year)", + columns = any_of(paste0("-", ry_max:1)) + ) %>% + tab_spanner( + label = "Post-treatment (relative year)", + columns = any_of(c("0", paste0("+", 1:ry_max))) + ) %>% + sub_zero(zero_text = "—") %>% + tab_options(table.font.size = "small") +``` + +@fig-es-fd-sfh-robust repeats the always-SFH FD event study restricted to cohorts 2017 and later — the earliest cohort with at least one pre-treatment FD observation. The result is unchanged: all estimates are statistically indistinguishable from zero throughout the full time horizon, with no systematic trend. + +```{r} +#| label: fig-es-fd-sfh-robust +#| fig-cap: "First-difference event study: always-SFH, cohorts 2017 and later only (cohorts 2015–2016 excluded — no pre-treatment data in FD sample)" +es_fd_sfh_robust <- feols( + d_log_assessment ~ sunab(first_year_treated, assessment_year) | + neighbourhood_name^assessment_year, + data = prepped_sfh %>% + filter(!is.na(d_log_assessment), first_year_treated > 2016), + cluster = ~account_number +) + +iplot( + es_fd_sfh_robust, + xlab = "Years relative to first nearby permit (≥6 units, within 50m)", + main = "", + ci_level = 0.95 +) +abline(v = -0.5, lty = 2, col = "grey50") +``` + + +## Caveats + +**Parallel trends is untestable.** Flat pre-trends are necessary but not sufficient evidence for a causal interpretation. A time-varying confounder that begins exactly when the permit is issued — say, a developer specifically targeting blocks that are about to appreciate for unrelated reasons — could still bias the estimates. The flat pre-trends make this story less plausible, but it cannot be ruled out. + +**Developer selection likely biases toward finding a positive effect.** If developers preferentially site multi-unit builds near properties that are already appreciating (e.g., near amenities, on major streets), the "treated" group would be expected to appreciate faster even without the infill. This would work against finding a null result, making the null finding more conservative, not less. + +**Assessed value is not sale price.** Edmonton's assessment data reflects the city's model of market value, not observed transactions. City-wide assessment methodology changes are absorbed by year fixed effects, but property-specific reassessment events are not. Using only properties where the same assessment method applies across all years would be a useful robustness check. + +**One-year lag.** The treatment indicator uses permits issued in year $t-1$ to predict assessments in year $t$. Construction timelines vary — larger buildings may take two or more years to complete — so some effects may be lagged further than the specification captures. The event study, which shows no effect even 4+ years post-permit, addresses this concern. + +**The always-SFH sample conditions on an endogenous outcome.** The always-SFH sample excludes properties that were themselves eventually redeveloped within 10m of a ≥6-unit permit during the study period. If infill pressure causes adjacent properties to sell and redevelop, this exclusion removes potentially affected properties. The always-SFH estimates should therefore be interpreted as the effect on properties that did not experience redevelopment pressure — a well-defined and policy-relevant group, but not a random subset. The bias direction is ambiguous but likely toward a more null result. + +## Conclusion + +Using year-over-year appreciation as the outcome, there is no evidence that multi-unit infill construction reduces neighbouring property values in Edmonton's mature neighbourhoods. The always-SFH estimates are near zero across both the ≥6-unit and ≥2-unit thresholds, and the all-residential estimates are near zero or slightly positive. The event study shows flat pre-trends and no post-treatment decline for stable single-family homes across the full post-treatment window. The all-residential sample does show a large positive spike at $t = 0$, almost certainly driven by properties approaching redevelopment being reassessed at land value — but this is a selection artefact that disappears in the always-SFH sample, confirming that stable homes are unaffected. All specifications use neighbourhood × year fixed effects, comparing treated and control properties within the same neighbourhood and year. + +This is consistent with the [preliminary post](../../2025/property-value-preliminary/) and with a growing literature finding that upzoning and infill construction do not harm existing homeowners. The fear that new apartments will hurt house prices is not supported by Edmonton's own data. It should not be a reason to restrict where housing can be built. \ No newline at end of file diff --git a/blog/2026/property-values/renv.lock b/blog/2026/property-values/renv.lock new file mode 100644 index 0000000..7d6aa67 --- /dev/null +++ b/blog/2026/property-values/renv.lock @@ -0,0 +1,2481 @@ +{ + "R": { + "Version": "4.5.2", + "Repositories": [ + { + "Name": "P3M", + "URL": "https://packagemanager.posit.co/cran/latest" + }, + { + "Name": "CRAN", + "URL": "https://cloud.r-project.org" + } + ] + }, + "Packages": { + "DBI": { + "Package": "DBI", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods" + ], + "Hash": "065ae649b05f1ff66bb0c793107508f5" + }, + "Formula": { + "Package": "Formula", + "Version": "1.2-5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "stats" + ], + "Hash": "7a29697b75e027767a53fde6c903eca7" + }, + "ISOcodes": { + "Package": "ISOcodes", + "Version": "2025.05.18", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "e15a512e4234d113186fb7c952641707" + }, + "KernSmooth": { + "Package": "KernSmooth", + "Version": "2.23-26", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "stats" + ], + "Hash": "2fb39782c07b5ad422b0448ae83f64c4" + }, + "MASS": { + "Package": "MASS", + "Version": "7.3-65", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "methods", + "stats", + "utils" + ], + "Hash": "a41d0fc833ea756a1136b60a437efe26" + }, + "R.methodsS3": { + "Package": "R.methodsS3", + "Version": "1.8.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "278c286fd6e9e75d0c2e8f731ea445c8" + }, + "R.oo": { + "Package": "R.oo", + "Version": "1.27.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R.methodsS3", + "methods", + "utils" + ], + "Hash": "a94afc14a90a68dd5043ceb9c089853b" + }, + "R.utils": { + "Package": "R.utils", + "Version": "2.13.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R.methodsS3", + "R.oo", + "methods", + "tools", + "utils" + ], + "Hash": "d32373d88da809f8974d5307481862b0" + }, + "R6": { + "Package": "R6", + "Version": "2.6.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "d4335fe7207f1c01ab8c41762f5840d4" + }, + "RColorBrewer": { + "Package": "RColorBrewer", + "Version": "1.1-3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "45f0398006e83a5b10b72a90663d8d8c" + }, + "Rcpp": { + "Package": "Rcpp", + "Version": "1.1.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods", + "utils" + ], + "Hash": "60df6f11cbeffbf9d50ad0852867f6b6" + }, + "S7": { + "Package": "S7", + "Version": "0.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "9da85950949574264f92f91f0e23de26" + }, + "V8": { + "Package": "V8", + "Version": "8.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp", + "curl", + "jsonlite", + "utils" + ], + "Hash": "f0301ca7b867eeb5c9b586a9e400729a" + }, + "askpass": { + "Package": "askpass", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "sys" + ], + "Hash": "c39f4155b3ceb1a9a2799d700fbd4b6a" + }, + "assertthat": { + "Package": "assertthat", + "Version": "0.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "tools" + ], + "Hash": "50c838a310445e954bc13f26f26a6ecf" + }, + "aws.s3": { + "Package": "aws.s3", + "Version": "0.3.22", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "aws.signature", + "base64enc", + "curl", + "digest", + "httr", + "tools", + "utils", + "xml2" + ], + "Hash": "cbb6690391d3ac39dfdfb4bff7250b4e" + }, + "aws.signature": { + "Package": "aws.signature", + "Version": "0.6.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "base64enc", + "digest" + ], + "Hash": "0006bcef272aad12f78dd5a85fc7f4fc" + }, + "backports": { + "Package": "backports", + "Version": "1.5.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "e1e1b9d75c37401117b636b7ae50827a" + }, + "base64enc": { + "Package": "base64enc", + "Version": "0.1-3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "543776ae6848fde2f48ff3816d0628bc" + }, + "bayestestR": { + "Package": "bayestestR", + "Version": "0.17.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "datawizard", + "graphics", + "insight", + "methods", + "stats", + "utils" + ], + "Hash": "06396210f1414b47a2702eb5d574934c" + }, + "bigD": { + "Package": "bigD", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "ad123ab90aa2fc795512f61ff6939c4a" + }, + "bit": { + "Package": "bit", + "Version": "4.6.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "ebe86ffd194564abdc895d87742d5a29" + }, + "bit64": { + "Package": "bit64", + "Version": "4.6.0-1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "bit", + "graphics", + "methods", + "stats", + "utils" + ], + "Hash": "4f572fbc586294afff277db583b9060f" + }, + "bitops": { + "Package": "bitops", + "Version": "1.0-9", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "d972ef991d58c19e6efa71b21f5e144b" + }, + "blob": { + "Package": "blob", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods", + "rlang", + "vctrs" + ], + "Hash": "1e0ae40898be928695fd90a80e816253" + }, + "broom": { + "Package": "broom", + "Version": "1.0.12", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "backports", + "cli", + "dplyr", + "generics", + "glue", + "lifecycle", + "purrr", + "rlang", + "stringr", + "tibble", + "tidyr" + ], + "Hash": "6cf2f6757591ea712c57c5d7bedc3c27" + }, + "bslib": { + "Package": "bslib", + "Version": "0.10.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "cachem", + "fastmap", + "grDevices", + "htmltools", + "jquerylib", + "jsonlite", + "lifecycle", + "memoise", + "mime", + "rlang", + "sass" + ], + "Hash": "d6072fb96c4868d8cb40d4071cdc472b" + }, + "cachem": { + "Package": "cachem", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "fastmap", + "rlang" + ], + "Hash": "cd9a672193789068eb5a2aad65a0dedf" + }, + "callr": { + "Package": "callr", + "Version": "3.7.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "processx", + "utils" + ], + "Hash": "d7e13f49c19103ece9e58ad2d83a7354" + }, + "cellranger": { + "Package": "cellranger", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "rematch", + "tibble" + ], + "Hash": "f61dbaec772ccd2e17705c1e872e9e7c" + }, + "checkmate": { + "Package": "checkmate", + "Version": "2.3.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "backports", + "utils" + ], + "Hash": "86cbe221fc19b56242f6c3eb0d4c5ab5" + }, + "class": { + "Package": "class", + "Version": "7.3-23", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "MASS", + "R", + "stats", + "utils" + ], + "Hash": "d0cb9cc838c3b43560bd958fc4317fdc" + }, + "classInt": { + "Package": "classInt", + "Version": "0.4-11", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "KernSmooth", + "R", + "class", + "e1071", + "grDevices", + "graphics", + "stats" + ], + "Hash": "f2af70314a63d7f025ae668f08bd933a" + }, + "cli": { + "Package": "cli", + "Version": "3.6.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "16850760556401a2eeb27d39bd11c9cb" + }, + "clipr": { + "Package": "clipr", + "Version": "0.8.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "utils" + ], + "Hash": "3f038e5ac7f41d4ac41ce658c85e3042" + }, + "commonmark": { + "Package": "commonmark", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "8cba62334c1088d21689d353a7e87663" + }, + "conflicted": { + "Package": "conflicted", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "memoise", + "rlang" + ], + "Hash": "bb097fccb22d156624fd07cd2894ddb6" + }, + "cpp11": { + "Package": "cpp11", + "Version": "0.5.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "af5958631ca49510aff96d0f5c0bbb76" + }, + "crayon": { + "Package": "crayon", + "Version": "1.5.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "grDevices", + "methods", + "utils" + ], + "Hash": "859d96e65ef198fd43e82b9628d593ef" + }, + "crosstalk": { + "Package": "crosstalk", + "Version": "1.2.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R6", + "htmltools", + "jsonlite", + "lazyeval" + ], + "Hash": "8b008bc619e0bbebb5646b3d37efdad1" + }, + "crul": { + "Package": "crul", + "Version": "1.6.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R6", + "curl", + "httpcode", + "jsonlite", + "lifecycle", + "mime", + "rlang", + "urltools" + ], + "Hash": "3aeb4061f5f9c25b3621a14c8e024a48" + }, + "curl": { + "Package": "curl", + "Version": "7.0.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "aa27e963d3deccf4bade44d06b976977" + }, + "data.table": { + "Package": "data.table", + "Version": "1.18.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "df99cd4333ce592df5173d6ad39b5c14" + }, + "datawizard": { + "Package": "datawizard", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "insight", + "stats", + "utils" + ], + "Hash": "6acfecf3792005ee2e2e1eb7ede6c1c1" + }, + "dbplyr": { + "Package": "dbplyr", + "Version": "2.5.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "DBI", + "R", + "R6", + "blob", + "cli", + "dplyr", + "glue", + "lifecycle", + "magrittr", + "methods", + "pillar", + "purrr", + "rlang", + "tibble", + "tidyr", + "tidyselect", + "utils", + "vctrs", + "withr" + ], + "Hash": "e38d7151c767b00b919091be4686e274" + }, + "digest": { + "Package": "digest", + "Version": "0.6.39", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "d18028e978a88b2b16ef8d400cb49adf" + }, + "dplyr": { + "Package": "dplyr", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "cli", + "generics", + "glue", + "lifecycle", + "magrittr", + "methods", + "pillar", + "rlang", + "tibble", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "fedd9d00c2944ff00a0e2696ccf048ec" + }, + "dreamerr": { + "Package": "dreamerr", + "Version": "1.5.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Formula", + "stringmagic", + "utils" + ], + "Hash": "f2e4bf22bbf86fb1eca4fd252901e23c" + }, + "dtplyr": { + "Package": "dtplyr", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "data.table", + "dplyr", + "glue", + "lifecycle", + "rlang", + "tibble", + "tidyselect", + "vctrs" + ], + "Hash": "50bbedd3d5b6a4ddc3c3c1602456aa35" + }, + "e1071": { + "Package": "e1071", + "Version": "1.7-17", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "class", + "grDevices", + "graphics", + "methods", + "proxy", + "stats", + "utils" + ], + "Hash": "9d516dde384526d4784166f888cd2c6c" + }, + "evaluate": { + "Package": "evaluate", + "Version": "1.0.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "94cf2c54237f6841cee68e3ba4ab5a14" + }, + "farver": { + "Package": "farver", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "P3M", + "Hash": "680887028577f3fa2a81e410ed0d6e42" + }, + "fastmap": { + "Package": "fastmap", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "P3M", + "Hash": "aa5e1cd11c2d15497494c5292d7ffcc8" + }, + "fixest": { + "Package": "fixest", + "Version": "0.13.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "dreamerr", + "grDevices", + "graphics", + "methods", + "nlme", + "numDeriv", + "sandwich", + "stats", + "stringmagic", + "tools", + "utils" + ], + "Hash": "f33d6987967224b1e60d29d26907f28a" + }, + "fontawesome": { + "Package": "fontawesome", + "Version": "0.5.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "htmltools", + "rlang" + ], + "Hash": "bd1297f9b5b1fc1372d19e2c4cd82215" + }, + "forcats": { + "Package": "forcats", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "tibble" + ], + "Hash": "f884a14605c6a9eb01db676eee793ba7" + }, + "fs": { + "Package": "fs", + "Version": "1.6.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods" + ], + "Hash": "7eb1e342eee7e0a7449c49cdaa526d39" + }, + "gargle": { + "Package": "gargle", + "Version": "1.6.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "fs", + "glue", + "httr", + "jsonlite", + "lifecycle", + "openssl", + "rappdirs", + "rlang", + "stats", + "utils", + "withr" + ], + "Hash": "99e4f3f00be5075372bb650a3e237a71" + }, + "generics": { + "Package": "generics", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods" + ], + "Hash": "4b29bf698d0c7bdb9f1e4976e7ade41d" + }, + "geojson": { + "Package": "geojson", + "Version": "0.3.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "jqr", + "jsonlite", + "lazyeval", + "magrittr", + "methods", + "protolite", + "sp" + ], + "Hash": "efc8d020709d1e1f9628a8d5362d193b" + }, + "geojsonio": { + "Package": "geojsonio", + "Version": "0.11.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "V8", + "crul", + "geojson", + "geojsonsf", + "jqr", + "jsonlite", + "magrittr", + "methods", + "readr", + "sf", + "sp" + ], + "Hash": "f0424e67a22ce09aaf89d6bc2b7f9431" + }, + "geojsonsf": { + "Package": "geojsonsf", + "Version": "2.0.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "geometries", + "jsonify", + "rapidjsonr", + "sfheaders" + ], + "Hash": "3096b36cc9ab822560d3217c068e4641" + }, + "geometries": { + "Package": "geometries", + "Version": "0.2.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp" + ], + "Hash": "cb7b9ad43bcf8d06d5c652f510ff5509" + }, + "ggplot2": { + "Package": "ggplot2", + "Version": "4.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "S7", + "cli", + "grDevices", + "grid", + "gtable", + "isoband", + "lifecycle", + "rlang", + "scales", + "stats", + "vctrs", + "withr" + ], + "Hash": "1bfa14b2a1668b3569dafb0478b2636b" + }, + "glue": { + "Package": "glue", + "Version": "1.8.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods" + ], + "Hash": "5899f1eaa825580172bb56c08266f37c" + }, + "googledrive": { + "Package": "googledrive", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "gargle", + "glue", + "httr", + "jsonlite", + "lifecycle", + "magrittr", + "pillar", + "purrr", + "rlang", + "tibble", + "utils", + "uuid", + "vctrs", + "withr" + ], + "Hash": "292be194aa519482c4b83f488a818ba3" + }, + "googlesheets4": { + "Package": "googlesheets4", + "Version": "1.1.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cellranger", + "cli", + "curl", + "gargle", + "glue", + "googledrive", + "httr", + "ids", + "lifecycle", + "magrittr", + "methods", + "purrr", + "rematch2", + "rlang", + "tibble", + "utils", + "vctrs", + "withr" + ], + "Hash": "376adbf359b416dbb30a76a2d2051ed5" + }, + "gt": { + "Package": "gt", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "bigD", + "bitops", + "cli", + "commonmark", + "dplyr", + "fs", + "glue", + "htmltools", + "htmlwidgets", + "juicyjuice", + "magrittr", + "markdown", + "reactable", + "rlang", + "sass", + "scales", + "tidyselect", + "vctrs", + "xml2" + ], + "Hash": "7153ac3985ed54f1a318590b73950329" + }, + "gtable": { + "Package": "gtable", + "Version": "0.3.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "glue", + "grid", + "lifecycle", + "rlang", + "stats" + ], + "Hash": "de949855009e2d4d0e52a844e30617ae" + }, + "haven": { + "Package": "haven", + "Version": "2.5.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "cpp11", + "forcats", + "hms", + "lifecycle", + "methods", + "readr", + "rlang", + "tibble", + "tidyselect", + "vctrs" + ], + "Hash": "437bc7804f8ffdfcfed38d0aead6a9d7" + }, + "here": { + "Package": "here", + "Version": "1.0.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "rprojroot" + ], + "Hash": "e5114f2abe04168238181913a8572358" + }, + "highr": { + "Package": "highr", + "Version": "0.11", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "xfun" + ], + "Hash": "d65ba49117ca223614f71b60d85b8ab7" + }, + "hms": { + "Package": "hms", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "cli", + "lifecycle", + "methods", + "pkgconfig", + "rlang", + "vctrs" + ], + "Hash": "2799ac720626cec589478b191e48b88b" + }, + "htmltools": { + "Package": "htmltools", + "Version": "0.5.9", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "base64enc", + "digest", + "fastmap", + "grDevices", + "rlang", + "utils" + ], + "Hash": "102298e238c14eb830cc4b5edd23c3e8" + }, + "htmlwidgets": { + "Package": "htmlwidgets", + "Version": "1.6.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "grDevices", + "htmltools", + "jsonlite", + "knitr", + "rmarkdown", + "yaml" + ], + "Hash": "04291cc45198225444a397606810ac37" + }, + "httpcode": { + "Package": "httpcode", + "Version": "0.3.0", + "Source": "Repository", + "Repository": "P3M", + "Hash": "13641a1c6d2cc98801b76764078e17ea" + }, + "httr": { + "Package": "httr", + "Version": "1.4.7", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "curl", + "jsonlite", + "mime", + "openssl" + ], + "Hash": "ac107251d9d9fd72f0ca8049988f1d7f" + }, + "ids": { + "Package": "ids", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "openssl", + "uuid" + ], + "Hash": "99df65cfef20e525ed38c3d2577f7190" + }, + "insight": { + "Package": "insight", + "Version": "1.4.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods", + "stats", + "utils" + ], + "Hash": "c3c6595dfc27f57a0031a6548076e0d8" + }, + "isoband": { + "Package": "isoband", + "Version": "0.3.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "cli", + "cpp11", + "grid", + "rlang", + "utils" + ], + "Hash": "0f9a864bbd7ce0232ad05cb76249cc1a" + }, + "jpeg": { + "Package": "jpeg", + "Version": "0.1-11", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "c23ab23c370d1ce3a7a80d8c0bdfa105" + }, + "jqr": { + "Package": "jqr", + "Version": "1.4.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "lazyeval", + "magrittr" + ], + "Hash": "25aad95d788314e4b307ead16059288d" + }, + "jquerylib": { + "Package": "jquerylib", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "htmltools" + ], + "Hash": "5aab57a3bd297eee1c1d862735972182" + }, + "jsonify": { + "Package": "jsonify", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "rapidjsonr" + ], + "Hash": "5edb07a22dcc39e90c2b4a761f9b39db" + }, + "jsonlite": { + "Package": "jsonlite", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "methods" + ], + "Hash": "b0776f526d36d8bd4a3344a88fe165c4" + }, + "juicyjuice": { + "Package": "juicyjuice", + "Version": "0.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "V8" + ], + "Hash": "3bcd11943da509341838da9399e18bce" + }, + "knitr": { + "Package": "knitr", + "Version": "1.51", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "evaluate", + "highr", + "methods", + "tools", + "xfun", + "yaml" + ], + "Hash": "27682babb50f03b6eb7939ea69ec79ca" + }, + "labeling": { + "Package": "labeling", + "Version": "0.4.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "graphics", + "stats" + ], + "Hash": "b64ec208ac5bc1852b285f665d6368b3" + }, + "lattice": { + "Package": "lattice", + "Version": "0.22-7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "grid", + "stats", + "utils" + ], + "Hash": "934f30aea6442867f57a610034ab06d3" + }, + "lazyeval": { + "Package": "lazyeval", + "Version": "0.2.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "d908914ae53b04d4c0c0fd72ecc35370" + }, + "leaflet": { + "Package": "leaflet", + "Version": "2.2.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "RColorBrewer", + "crosstalk", + "htmltools", + "htmlwidgets", + "jquerylib", + "leaflet.providers", + "magrittr", + "methods", + "png", + "raster", + "rlang", + "scales", + "sf", + "stats", + "viridisLite", + "xfun" + ], + "Hash": "da8aa03b2885c2b934923e6a53fe592a" + }, + "leaflet.providers": { + "Package": "leaflet.providers", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "htmltools" + ], + "Hash": "c0b81ad9d5d932772f7a457ac398cf36" + }, + "lifecycle": { + "Package": "lifecycle", + "Version": "1.0.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "rlang" + ], + "Hash": "36dbfe4fba6c064db50a671a90297c85" + }, + "litedown": { + "Package": "litedown", + "Version": "0.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "commonmark", + "utils", + "xfun" + ], + "Hash": "6b9435273e6506fbafa5909adf4abb88" + }, + "lubridate": { + "Package": "lubridate", + "Version": "1.9.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "generics", + "methods", + "timechange" + ], + "Hash": "be38bc740fc51783a78edb5a157e4104" + }, + "magick": { + "Package": "magick", + "Version": "2.9.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "curl", + "magrittr" + ], + "Hash": "8b43f0e49eb9585e9e7faf12145ee79e" + }, + "magrittr": { + "Package": "magrittr", + "Version": "2.0.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "8b3b213aa0c54a0dec254288ccb545d1" + }, + "mapboxapi": { + "Package": "mapboxapi", + "Version": "0.6.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "aws.s3", + "curl", + "dplyr", + "geojsonsf", + "htmltools", + "httr", + "jpeg", + "jsonlite", + "leaflet", + "magick", + "png", + "protolite", + "purrr", + "raster", + "rlang", + "sf", + "slippymath", + "stringi", + "tidyr", + "units" + ], + "Hash": "8a8f8bcb89ca75e45b22e7ee88e211de" + }, + "marginaleffects": { + "Package": "marginaleffects", + "Version": "0.32.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Formula", + "R", + "backports", + "checkmate", + "data.table", + "generics", + "insight", + "methods", + "rlang" + ], + "Hash": "fecb96ffc7d24ec956a4ff4980264952" + }, + "markdown": { + "Package": "markdown", + "Version": "2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "litedown", + "utils", + "xfun" + ], + "Hash": "b4349847250b103bbbb8bc6819c4fbca" + }, + "memoise": { + "Package": "memoise", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "cachem", + "rlang" + ], + "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c" + }, + "mime": { + "Package": "mime", + "Version": "0.13", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "tools" + ], + "Hash": "0ec19f34c72fab674d8f2b4b1c6410e1" + }, + "modelr": { + "Package": "modelr", + "Version": "0.1.11", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "broom", + "magrittr", + "purrr", + "rlang", + "tibble", + "tidyr", + "tidyselect", + "vctrs" + ], + "Hash": "4f50122dc256b1b6996a4703fecea821" + }, + "modelsummary": { + "Package": "modelsummary", + "Version": "2.6.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "checkmate", + "data.table", + "generics", + "glue", + "insight", + "methods", + "parameters", + "performance", + "tables", + "tinytable" + ], + "Hash": "300c51ccba8888aa7d24b55bf726228e" + }, + "mountainmathHelpers": { + "Package": "mountainmathHelpers", + "Version": "0.1.4", + "Source": "GitHub", + "RemoteType": "github", + "RemoteHost": "api.github.com", + "RemoteUsername": "mountainmath", + "RemoteRepo": "mountainmathhelpers", + "RemoteRef": "master", + "RemoteSha": "6af7c868601c9c7434f01169bfbe7c4b3636fd9c", + "Requirements": [ + "R.utils", + "aws.s3", + "digest", + "dplyr", + "geojsonsf", + "ggplot2", + "httr", + "jsonlite", + "mapboxapi", + "readr", + "rlang", + "rmapzen", + "sf", + "slippymath" + ], + "Hash": "cea5db1c698d774b09c94885abd84403" + }, + "nlme": { + "Package": "nlme", + "Version": "3.1-168", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "graphics", + "lattice", + "stats", + "utils" + ], + "Hash": "b1d2ea08d5d392831fbc32c872362b06" + }, + "numDeriv": { + "Package": "numDeriv", + "Version": "2016.8-1.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "df58958f293b166e4ab885ebcad90e02" + }, + "openssl": { + "Package": "openssl", + "Version": "2.3.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "askpass" + ], + "Hash": "d5811dade9cd3a34a9038a45f1a59bae" + }, + "parameters": { + "Package": "parameters", + "Version": "0.28.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "bayestestR", + "datawizard", + "graphics", + "insight", + "methods", + "stats", + "utils" + ], + "Hash": "5c812a68308c47fa9cafbfebccc3e356" + }, + "performance": { + "Package": "performance", + "Version": "0.16.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "bayestestR", + "datawizard", + "insight", + "methods", + "stats", + "utils" + ], + "Hash": "d02d66e01f1d11197809c79bb19d628f" + }, + "pillar": { + "Package": "pillar", + "Version": "1.11.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "cli", + "glue", + "lifecycle", + "rlang", + "utf8", + "utils", + "vctrs" + ], + "Hash": "1395e64f2689ffd503657778e810cee2" + }, + "pkgconfig": { + "Package": "pkgconfig", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "utils" + ], + "Hash": "01f28d4278f15c76cddbea05899c5d6f" + }, + "png": { + "Package": "png", + "Version": "0.1-8", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "bd54ba8a0a5faded999a7aab6e46b374" + }, + "prettyunits": { + "Package": "prettyunits", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "6b01fc98b1e86c4f705ce9dcfd2f57c7" + }, + "processx": { + "Package": "processx", + "Version": "3.8.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "ps", + "utils" + ], + "Hash": "720161b280b0a35f4d1490ead2fe81d0" + }, + "progress": { + "Package": "progress", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "crayon", + "hms", + "prettyunits" + ], + "Hash": "f4625e061cb2865f111b47ff163a5ca6" + }, + "protolite": { + "Package": "protolite", + "Version": "2.3.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp", + "jsonlite" + ], + "Hash": "ea2364e73971f7e570bffc59868e3912" + }, + "proxy": { + "Package": "proxy", + "Version": "0.4-29", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "stats", + "utils" + ], + "Hash": "b6c826e897b46b163c51a3b990113a21" + }, + "ps": { + "Package": "ps", + "Version": "1.9.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "093688087b0bacce6ba2f661f36328e2" + }, + "purrr": { + "Package": "purrr", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "lifecycle", + "magrittr", + "rlang", + "vctrs" + ], + "Hash": "0154ac5b9ef4df1a7be3a54602e781cf" + }, + "ragg": { + "Package": "ragg", + "Version": "1.5.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "systemfonts", + "textshaping" + ], + "Hash": "cdb40b21711a8870f305b24226698f9f" + }, + "rapidjsonr": { + "Package": "rapidjsonr", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "P3M", + "Hash": "b6a97237ee07c7fcfe836f1b6ba882b0" + }, + "rappdirs": { + "Package": "rappdirs", + "Version": "0.3.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "f146a5bfc94db048309712535d4d0aee" + }, + "raster": { + "Package": "raster", + "Version": "3.6-32", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "methods", + "sp", + "terra" + ], + "Hash": "1e193fc2c727a6f83cf95d9e16024423" + }, + "reactR": { + "Package": "reactR", + "Version": "0.6.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "htmltools" + ], + "Hash": "b8e3d93f508045812f47136c7c44c251" + }, + "reactable": { + "Package": "reactable", + "Version": "0.4.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "digest", + "htmltools", + "htmlwidgets", + "jsonlite", + "reactR" + ], + "Hash": "abfd6fa3794ff78116123d95845e0c32" + }, + "readr": { + "Package": "readr", + "Version": "2.1.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "cli", + "clipr", + "cpp11", + "crayon", + "hms", + "lifecycle", + "methods", + "rlang", + "tibble", + "tzdb", + "utils", + "vroom" + ], + "Hash": "141ebcec1bf55707751c7956a34d93db" + }, + "readxl": { + "Package": "readxl", + "Version": "1.4.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cellranger", + "cpp11", + "progress", + "tibble", + "utils" + ], + "Hash": "18948de59f05d38a44d3e5065a76b4b6" + }, + "rematch": { + "Package": "rematch", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "P3M", + "Hash": "cbff1b666c6fa6d21202f07e2318d4f1" + }, + "rematch2": { + "Package": "rematch2", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "tibble" + ], + "Hash": "76c9e04c712a05848ae7a23d2f170a40" + }, + "renv": { + "Package": "renv", + "Version": "1.0.11", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "utils" + ], + "Hash": "47623f66b4e80b3b0587bc5d7b309888" + }, + "reprex": { + "Package": "reprex", + "Version": "2.1.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "callr", + "cli", + "clipr", + "fs", + "glue", + "knitr", + "lifecycle", + "rlang", + "rmarkdown", + "rstudioapi", + "utils", + "withr" + ], + "Hash": "97b1d5361a24d9fb588db7afe3e5bcbf" + }, + "rlang": { + "Package": "rlang", + "Version": "1.1.7", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "34c0d101f4613098abc538b82e0d86c5" + }, + "rmapzen": { + "Package": "rmapzen", + "Version": "0.5.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "ISOcodes", + "R", + "assertthat", + "digest", + "dplyr", + "geojsonio", + "httr", + "jsonlite", + "purrr", + "sf", + "tibble", + "tidyr", + "utils" + ], + "Hash": "5f2da6eb8d2ea66342ea0799b37fb802" + }, + "rmarkdown": { + "Package": "rmarkdown", + "Version": "2.30", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "bslib", + "evaluate", + "fontawesome", + "htmltools", + "jquerylib", + "jsonlite", + "knitr", + "methods", + "tinytex", + "tools", + "utils", + "xfun", + "yaml" + ], + "Hash": "efe19db0fde0fff13cea7eec6f695021" + }, + "rprojroot": { + "Package": "rprojroot", + "Version": "2.1.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "b2453de2d29aa646afe4781defdc7903" + }, + "rstudioapi": { + "Package": "rstudioapi", + "Version": "0.18.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "d6e1ecf8e39b6d53c8acde372b2f92d1" + }, + "rvest": { + "Package": "rvest", + "Version": "1.0.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "glue", + "httr", + "lifecycle", + "magrittr", + "rlang", + "selectr", + "tibble", + "xml2" + ], + "Hash": "2804ddcd7737082306c559d919886546" + }, + "s2": { + "Package": "s2", + "Version": "1.1.9", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "wk" + ], + "Hash": "4e664a5d610d58f27ec196e96cdb7f6f" + }, + "sandwich": { + "Package": "sandwich", + "Version": "3.1-1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "stats", + "utils", + "zoo" + ], + "Hash": "072bb2d27425f2a58fe71fe1080676ce" + }, + "sass": { + "Package": "sass", + "Version": "0.4.10", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R6", + "fs", + "htmltools", + "rappdirs", + "rlang" + ], + "Hash": "3fb78d066fb92299b1d13f6a7c9a90a8" + }, + "scales": { + "Package": "scales", + "Version": "1.4.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "RColorBrewer", + "cli", + "farver", + "glue", + "labeling", + "lifecycle", + "rlang", + "viridisLite" + ], + "Hash": "c5bba8f0d1df8c4b9538a40570798d9b" + }, + "selectr": { + "Package": "selectr", + "Version": "0.5-1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "methods", + "stringr" + ], + "Hash": "fb6f4aacfcc16539458c66b698339e69" + }, + "sf": { + "Package": "sf", + "Version": "1.0-24", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "DBI", + "R", + "Rcpp", + "classInt", + "grDevices", + "graphics", + "grid", + "magrittr", + "methods", + "s2", + "stats", + "tools", + "units", + "utils" + ], + "Hash": "7a4756aedf70812aa33fba3d29529424" + }, + "sfheaders": { + "Package": "sfheaders", + "Version": "0.4.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "geometries" + ], + "Hash": "c655cae84ce671c8aa1067cbf2ff0fe4" + }, + "slippymath": { + "Package": "slippymath", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "png", + "purrr", + "raster", + "stats" + ], + "Hash": "abdaf883004a4791545655d79ca3aae0" + }, + "sp": { + "Package": "sp", + "Version": "2.2-0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "grDevices", + "graphics", + "grid", + "lattice", + "methods", + "stats", + "utils" + ], + "Hash": "d9ff3b753db98bc50650314c8782abe6" + }, + "stringi": { + "Package": "stringi", + "Version": "1.8.7", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "stats", + "tools", + "utils" + ], + "Hash": "2b56088e23bdd58f89aebf43a0913457" + }, + "stringmagic": { + "Package": "stringmagic", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp", + "stats", + "utils" + ], + "Hash": "b972dfa36bb17a053cb5a21c1b3edc0f" + }, + "stringr": { + "Package": "stringr", + "Version": "1.6.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "stringi", + "vctrs" + ], + "Hash": "d47392652eedc68bf916657347ff2526" + }, + "sys": { + "Package": "sys", + "Version": "3.4.3", + "Source": "Repository", + "Repository": "P3M", + "Hash": "de342ebfebdbf40477d0758d05426646" + }, + "systemfonts": { + "Package": "systemfonts", + "Version": "1.3.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "base64enc", + "cpp11", + "grid", + "jsonlite", + "lifecycle", + "tools", + "utils" + ], + "Hash": "4fae513a3bb1a155943d1e9d1ae467ec" + }, + "tables": { + "Package": "tables", + "Version": "0.9.33", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "htmltools", + "knitr", + "stats", + "utils" + ], + "Hash": "fe19a0ed754e2ab39f85bac09f5f01cc" + }, + "terra": { + "Package": "terra", + "Version": "1.8-93", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "methods" + ], + "Hash": "bb3e2b0e01eeeed8c3e828faaf6c68b5" + }, + "textshaping": { + "Package": "textshaping", + "Version": "1.0.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cpp11", + "lifecycle", + "stats", + "stringi", + "systemfonts", + "utils" + ], + "Hash": "477d70e23914730aa7f5c5fd351f4721" + }, + "tibble": { + "Package": "tibble", + "Version": "3.3.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "lifecycle", + "magrittr", + "methods", + "pillar", + "pkgconfig", + "rlang", + "utils", + "vctrs" + ], + "Hash": "c55df870972551cac674b50cadb2d51f" + }, + "tidyr": { + "Package": "tidyr", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "cpp11", + "dplyr", + "glue", + "lifecycle", + "magrittr", + "purrr", + "rlang", + "stringr", + "tibble", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "a4fa2f5876396f04814cb9d8d9ab89e9" + }, + "tidyselect": { + "Package": "tidyselect", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang", + "vctrs", + "withr" + ], + "Hash": "829f27b9c4919c16b593794a6344d6c0" + }, + "tidyverse": { + "Package": "tidyverse", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "broom", + "cli", + "conflicted", + "dbplyr", + "dplyr", + "dtplyr", + "forcats", + "ggplot2", + "googledrive", + "googlesheets4", + "haven", + "hms", + "httr", + "jsonlite", + "lubridate", + "magrittr", + "modelr", + "pillar", + "purrr", + "ragg", + "readr", + "readxl", + "reprex", + "rlang", + "rstudioapi", + "rvest", + "stringr", + "tibble", + "tidyr", + "xml2" + ], + "Hash": "c328568cd14ea89a83bd4ca7f54ae07e" + }, + "timechange": { + "Package": "timechange", + "Version": "0.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "39c40cb1ad47a4cc384a34a22a29463f" + }, + "tinytable": { + "Package": "tinytable", + "Version": "0.16.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods" + ], + "Hash": "c2e748cbeefd0ca50d5eafc056250f26" + }, + "tinytex": { + "Package": "tinytex", + "Version": "0.58", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "xfun" + ], + "Hash": "03af3ad04817f3019de8ee5c73dab807" + }, + "triebeard": { + "Package": "triebeard", + "Version": "0.4.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp" + ], + "Hash": "642507a148b0dd9b5620177e0a044413" + }, + "tzdb": { + "Package": "tzdb", + "Version": "0.5.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "09e3961e87b7bafa4a9340bbb34aeda8" + }, + "units": { + "Package": "units", + "Version": "1.0-0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp" + ], + "Hash": "3797c73fd3bde8b1601a4e1bf53557ac" + }, + "urltools": { + "Package": "urltools", + "Version": "1.7.3.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "methods", + "triebeard" + ], + "Hash": "0951eeef49e3df040dfc67ce75a052ac" + }, + "utf8": { + "Package": "utf8", + "Version": "1.2.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "d526d558be176e9ceb68c3d1e83479b7" + }, + "uuid": { + "Package": "uuid", + "Version": "1.2-2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "528fc9e90d70a6a115e21164f37b2c64" + }, + "vctrs": { + "Package": "vctrs", + "Version": "0.7.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang" + ], + "Hash": "c64e64d93489bb62bb8747bbb9e06c09" + }, + "viridisLite": { + "Package": "viridisLite", + "Version": "0.4.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "c826c7c4241b6fc89ff55aaea3fa7491" + }, + "vroom": { + "Package": "vroom", + "Version": "1.7.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bit64", + "cli", + "cpp11", + "crayon", + "glue", + "hms", + "lifecycle", + "methods", + "progress", + "rlang", + "stats", + "tibble", + "tidyselect", + "tzdb", + "vctrs", + "withr" + ], + "Hash": "255cb6f090718455ff89cbc28cb5eea7" + }, + "withr": { + "Package": "withr", + "Version": "3.0.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "grDevices", + "graphics" + ], + "Hash": "cc2d62c76458d425210d1eb1478b30b4" + }, + "wk": { + "Package": "wk", + "Version": "0.9.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "10fb21ed42dbd4ed9162aaab818146e3" + }, + "xfun": { + "Package": "xfun", + "Version": "0.56", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "stats", + "tools" + ], + "Hash": "f1f18d352a39c6252932da4faa029cdd" + }, + "xml2": { + "Package": "xml2", + "Version": "1.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "methods", + "rlang" + ], + "Hash": "d8e98d08a4a4d03f5052acc6e6204b99" + }, + "yaml": { + "Package": "yaml", + "Version": "2.3.12", + "Source": "Repository", + "Repository": "P3M", + "Hash": "7cd77cb32abd9220d744307e9fc94ffb" + }, + "zoo": { + "Package": "zoo", + "Version": "1.8-15", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "grDevices", + "graphics", + "lattice", + "stats", + "utils" + ], + "Hash": "3f85ec88dadbaa3301917cea59727329" + } + } +} diff --git a/blog/2026/property-values/renv/.gitignore b/blog/2026/property-values/renv/.gitignore new file mode 100644 index 0000000..0ec0cbb --- /dev/null +++ b/blog/2026/property-values/renv/.gitignore @@ -0,0 +1,7 @@ +library/ +local/ +cellar/ +lock/ +python/ +sandbox/ +staging/ diff --git a/blog/2026/property-values/renv/activate.R b/blog/2026/property-values/renv/activate.R new file mode 100644 index 0000000..0eb5108 --- /dev/null +++ b/blog/2026/property-values/renv/activate.R @@ -0,0 +1,1305 @@ + +local({ + + # the requested version of renv + version <- "1.0.11" + attr(version, "sha") <- NULL + + # the project directory + project <- Sys.getenv("RENV_PROJECT") + if (!nzchar(project)) + project <- getwd() + + # use start-up diagnostics if enabled + diagnostics <- Sys.getenv("RENV_STARTUP_DIAGNOSTICS", unset = "FALSE") + if (diagnostics) { + start <- Sys.time() + profile <- tempfile("renv-startup-", fileext = ".Rprof") + utils::Rprof(profile) + on.exit({ + utils::Rprof(NULL) + elapsed <- signif(difftime(Sys.time(), start, units = "auto"), digits = 2L) + writeLines(sprintf("- renv took %s to run the autoloader.", format(elapsed))) + writeLines(sprintf("- Profile: %s", profile)) + print(utils::summaryRprof(profile)) + }, add = TRUE) + } + + # figure out whether the autoloader is enabled + enabled <- local({ + + # first, check config option + override <- getOption("renv.config.autoloader.enabled") + if (!is.null(override)) + return(override) + + # if we're being run in a context where R_LIBS is already set, + # don't load -- presumably we're being run as a sub-process and + # the parent process has already set up library paths for us + rcmd <- Sys.getenv("R_CMD", unset = NA) + rlibs <- Sys.getenv("R_LIBS", unset = NA) + if (!is.na(rlibs) && !is.na(rcmd)) + return(FALSE) + + # next, check environment variables + # TODO: prefer using the configuration one in the future + envvars <- c( + "RENV_CONFIG_AUTOLOADER_ENABLED", + "RENV_AUTOLOADER_ENABLED", + "RENV_ACTIVATE_PROJECT" + ) + + for (envvar in envvars) { + envval <- Sys.getenv(envvar, unset = NA) + if (!is.na(envval)) + return(tolower(envval) %in% c("true", "t", "1")) + } + + # enable by default + TRUE + + }) + + # bail if we're not enabled + if (!enabled) { + + # if we're not enabled, we might still need to manually load + # the user profile here + profile <- Sys.getenv("R_PROFILE_USER", unset = "~/.Rprofile") + if (file.exists(profile)) { + cfg <- Sys.getenv("RENV_CONFIG_USER_PROFILE", unset = "TRUE") + if (tolower(cfg) %in% c("true", "t", "1")) + sys.source(profile, envir = globalenv()) + } + + return(FALSE) + + } + + # avoid recursion + if (identical(getOption("renv.autoloader.running"), TRUE)) { + warning("ignoring recursive attempt to run renv autoloader") + return(invisible(TRUE)) + } + + # signal that we're loading renv during R startup + options(renv.autoloader.running = TRUE) + on.exit(options(renv.autoloader.running = NULL), add = TRUE) + + # signal that we've consented to use renv + options(renv.consent = TRUE) + + # load the 'utils' package eagerly -- this ensures that renv shims, which + # mask 'utils' packages, will come first on the search path + library(utils, lib.loc = .Library) + + # unload renv if it's already been loaded + if ("renv" %in% loadedNamespaces()) + unloadNamespace("renv") + + # load bootstrap tools + ansify <- function(text) { + if (renv_ansify_enabled()) + renv_ansify_enhanced(text) + else + renv_ansify_default(text) + } + + renv_ansify_enabled <- function() { + + override <- Sys.getenv("RENV_ANSIFY_ENABLED", unset = NA) + if (!is.na(override)) + return(as.logical(override)) + + pane <- Sys.getenv("RSTUDIO_CHILD_PROCESS_PANE", unset = NA) + if (identical(pane, "build")) + return(FALSE) + + testthat <- Sys.getenv("TESTTHAT", unset = "false") + if (tolower(testthat) %in% "true") + return(FALSE) + + iderun <- Sys.getenv("R_CLI_HAS_HYPERLINK_IDE_RUN", unset = "false") + if (tolower(iderun) %in% "false") + return(FALSE) + + TRUE + + } + + renv_ansify_default <- function(text) { + text + } + + renv_ansify_enhanced <- function(text) { + + # R help links + pattern <- "`\\?(renv::(?:[^`])+)`" + replacement <- "`\033]8;;ide:help:\\1\a?\\1\033]8;;\a`" + text <- gsub(pattern, replacement, text, perl = TRUE) + + # runnable code + pattern <- "`(renv::(?:[^`])+)`" + replacement <- "`\033]8;;ide:run:\\1\a\\1\033]8;;\a`" + text <- gsub(pattern, replacement, text, perl = TRUE) + + # return ansified text + text + + } + + renv_ansify_init <- function() { + + envir <- renv_envir_self() + if (renv_ansify_enabled()) + assign("ansify", renv_ansify_enhanced, envir = envir) + else + assign("ansify", renv_ansify_default, envir = envir) + + } + + `%||%` <- function(x, y) { + if (is.null(x)) y else x + } + + catf <- function(fmt, ..., appendLF = TRUE) { + + quiet <- getOption("renv.bootstrap.quiet", default = FALSE) + if (quiet) + return(invisible()) + + msg <- sprintf(fmt, ...) + cat(msg, file = stdout(), sep = if (appendLF) "\n" else "") + + invisible(msg) + + } + + header <- function(label, + ..., + prefix = "#", + suffix = "-", + n = min(getOption("width"), 78)) + { + label <- sprintf(label, ...) + n <- max(n - nchar(label) - nchar(prefix) - 2L, 8L) + if (n <= 0) + return(paste(prefix, label)) + + tail <- paste(rep.int(suffix, n), collapse = "") + paste0(prefix, " ", label, " ", tail) + + } + + heredoc <- function(text, leave = 0) { + + # remove leading, trailing whitespace + trimmed <- gsub("^\\s*\\n|\\n\\s*$", "", text) + + # split into lines + lines <- strsplit(trimmed, "\n", fixed = TRUE)[[1L]] + + # compute common indent + indent <- regexpr("[^[:space:]]", lines) + common <- min(setdiff(indent, -1L)) - leave + text <- paste(substring(lines, common), collapse = "\n") + + # substitute in ANSI links for executable renv code + ansify(text) + + } + + startswith <- function(string, prefix) { + substring(string, 1, nchar(prefix)) == prefix + } + + bootstrap <- function(version, library) { + + friendly <- renv_bootstrap_version_friendly(version) + section <- header(sprintf("Bootstrapping renv %s", friendly)) + catf(section) + + # attempt to download renv + catf("- Downloading renv ... ", appendLF = FALSE) + withCallingHandlers( + tarball <- renv_bootstrap_download(version), + error = function(err) { + catf("FAILED") + stop("failed to download:\n", conditionMessage(err)) + } + ) + catf("OK") + on.exit(unlink(tarball), add = TRUE) + + # now attempt to install + catf("- Installing renv ... ", appendLF = FALSE) + withCallingHandlers( + status <- renv_bootstrap_install(version, tarball, library), + error = function(err) { + catf("FAILED") + stop("failed to install:\n", conditionMessage(err)) + } + ) + catf("OK") + + # add empty line to break up bootstrapping from normal output + catf("") + + return(invisible()) + } + + renv_bootstrap_tests_running <- function() { + getOption("renv.tests.running", default = FALSE) + } + + renv_bootstrap_repos <- function() { + + # get CRAN repository + cran <- getOption("renv.repos.cran", "https://cloud.r-project.org") + + # check for repos override + repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA) + if (!is.na(repos)) { + + # check for RSPM; if set, use a fallback repository for renv + rspm <- Sys.getenv("RSPM", unset = NA) + if (identical(rspm, repos)) + repos <- c(RSPM = rspm, CRAN = cran) + + return(repos) + + } + + # check for lockfile repositories + repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity) + if (!inherits(repos, "error") && length(repos)) + return(repos) + + # retrieve current repos + repos <- getOption("repos") + + # ensure @CRAN@ entries are resolved + repos[repos == "@CRAN@"] <- cran + + # add in renv.bootstrap.repos if set + default <- c(FALLBACK = "https://cloud.r-project.org") + extra <- getOption("renv.bootstrap.repos", default = default) + repos <- c(repos, extra) + + # remove duplicates that might've snuck in + dupes <- duplicated(repos) | duplicated(names(repos)) + repos[!dupes] + + } + + renv_bootstrap_repos_lockfile <- function() { + + lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock") + if (!file.exists(lockpath)) + return(NULL) + + lockfile <- tryCatch(renv_json_read(lockpath), error = identity) + if (inherits(lockfile, "error")) { + warning(lockfile) + return(NULL) + } + + repos <- lockfile$R$Repositories + if (length(repos) == 0) + return(NULL) + + keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1)) + vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1)) + names(vals) <- keys + + return(vals) + + } + + renv_bootstrap_download <- function(version) { + + sha <- attr(version, "sha", exact = TRUE) + + methods <- if (!is.null(sha)) { + + # attempting to bootstrap a development version of renv + c( + function() renv_bootstrap_download_tarball(sha), + function() renv_bootstrap_download_github(sha) + ) + + } else { + + # attempting to bootstrap a release version of renv + c( + function() renv_bootstrap_download_tarball(version), + function() renv_bootstrap_download_cran_latest(version), + function() renv_bootstrap_download_cran_archive(version) + ) + + } + + for (method in methods) { + path <- tryCatch(method(), error = identity) + if (is.character(path) && file.exists(path)) + return(path) + } + + stop("All download methods failed") + + } + + renv_bootstrap_download_impl <- function(url, destfile) { + + mode <- "wb" + + # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715 + fixup <- + Sys.info()[["sysname"]] == "Windows" && + substring(url, 1L, 5L) == "file:" + + if (fixup) + mode <- "w+b" + + args <- list( + url = url, + destfile = destfile, + mode = mode, + quiet = TRUE + ) + + if ("headers" %in% names(formals(utils::download.file))) { + headers <- renv_bootstrap_download_custom_headers(url) + if (length(headers) && is.character(headers)) + args$headers <- headers + } + + do.call(utils::download.file, args) + + } + + renv_bootstrap_download_custom_headers <- function(url) { + + headers <- getOption("renv.download.headers") + if (is.null(headers)) + return(character()) + + if (!is.function(headers)) + stopf("'renv.download.headers' is not a function") + + headers <- headers(url) + if (length(headers) == 0L) + return(character()) + + if (is.list(headers)) + headers <- unlist(headers, recursive = FALSE, use.names = TRUE) + + ok <- + is.character(headers) && + is.character(names(headers)) && + all(nzchar(names(headers))) + + if (!ok) + stop("invocation of 'renv.download.headers' did not return a named character vector") + + headers + + } + + renv_bootstrap_download_cran_latest <- function(version) { + + spec <- renv_bootstrap_download_cran_latest_find(version) + type <- spec$type + repos <- spec$repos + + baseurl <- utils::contrib.url(repos = repos, type = type) + ext <- if (identical(type, "source")) + ".tar.gz" + else if (Sys.info()[["sysname"]] == "Windows") + ".zip" + else + ".tgz" + name <- sprintf("renv_%s%s", version, ext) + url <- paste(baseurl, name, sep = "/") + + destfile <- file.path(tempdir(), name) + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (inherits(status, "condition")) + return(FALSE) + + # report success and return + destfile + + } + + renv_bootstrap_download_cran_latest_find <- function(version) { + + # check whether binaries are supported on this system + binary <- + getOption("renv.bootstrap.binary", default = TRUE) && + !identical(.Platform$pkgType, "source") && + !identical(getOption("pkgType"), "source") && + Sys.info()[["sysname"]] %in% c("Darwin", "Windows") + + types <- c(if (binary) "binary", "source") + + # iterate over types + repositories + for (type in types) { + for (repos in renv_bootstrap_repos()) { + + # build arguments for utils::available.packages() call + args <- list(type = type, repos = repos) + + # add custom headers if available -- note that + # utils::available.packages() will pass this to download.file() + if ("headers" %in% names(formals(utils::download.file))) { + headers <- renv_bootstrap_download_custom_headers(repos) + if (length(headers) && is.character(headers)) + args$headers <- headers + } + + # retrieve package database + db <- tryCatch( + as.data.frame( + do.call(utils::available.packages, args), + stringsAsFactors = FALSE + ), + error = identity + ) + + if (inherits(db, "error")) + next + + # check for compatible entry + entry <- db[db$Package %in% "renv" & db$Version %in% version, ] + if (nrow(entry) == 0) + next + + # found it; return spec to caller + spec <- list(entry = entry, type = type, repos = repos) + return(spec) + + } + } + + # if we got here, we failed to find renv + fmt <- "renv %s is not available from your declared package repositories" + stop(sprintf(fmt, version)) + + } + + renv_bootstrap_download_cran_archive <- function(version) { + + name <- sprintf("renv_%s.tar.gz", version) + repos <- renv_bootstrap_repos() + urls <- file.path(repos, "src/contrib/Archive/renv", name) + destfile <- file.path(tempdir(), name) + + for (url in urls) { + + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (identical(status, 0L)) + return(destfile) + + } + + return(FALSE) + + } + + renv_bootstrap_download_tarball <- function(version) { + + # if the user has provided the path to a tarball via + # an environment variable, then use it + tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA) + if (is.na(tarball)) + return() + + # allow directories + if (dir.exists(tarball)) { + name <- sprintf("renv_%s.tar.gz", version) + tarball <- file.path(tarball, name) + } + + # bail if it doesn't exist + if (!file.exists(tarball)) { + + # let the user know we weren't able to honour their request + fmt <- "- RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist." + msg <- sprintf(fmt, tarball) + warning(msg) + + # bail + return() + + } + + catf("- Using local tarball '%s'.", tarball) + tarball + + } + + renv_bootstrap_github_token <- function() { + for (envvar in c("GITHUB_TOKEN", "GITHUB_PAT", "GH_TOKEN")) { + envval <- Sys.getenv(envvar, unset = NA) + if (!is.na(envval)) + return(envval) + } + } + + renv_bootstrap_download_github <- function(version) { + + enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE") + if (!identical(enabled, "TRUE")) + return(FALSE) + + # prepare download options + token <- renv_bootstrap_github_token() + if (nzchar(Sys.which("curl")) && nzchar(token)) { + fmt <- "--location --fail --header \"Authorization: token %s\"" + extra <- sprintf(fmt, token) + saved <- options("download.file.method", "download.file.extra") + options(download.file.method = "curl", download.file.extra = extra) + on.exit(do.call(base::options, saved), add = TRUE) + } else if (nzchar(Sys.which("wget")) && nzchar(token)) { + fmt <- "--header=\"Authorization: token %s\"" + extra <- sprintf(fmt, token) + saved <- options("download.file.method", "download.file.extra") + options(download.file.method = "wget", download.file.extra = extra) + on.exit(do.call(base::options, saved), add = TRUE) + } + + url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version) + name <- sprintf("renv_%s.tar.gz", version) + destfile <- file.path(tempdir(), name) + + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (!identical(status, 0L)) + return(FALSE) + + renv_bootstrap_download_augment(destfile) + + return(destfile) + + } + + # Add Sha to DESCRIPTION. This is stop gap until #890, after which we + # can use renv::install() to fully capture metadata. + renv_bootstrap_download_augment <- function(destfile) { + sha <- renv_bootstrap_git_extract_sha1_tar(destfile) + if (is.null(sha)) { + return() + } + + # Untar + tempdir <- tempfile("renv-github-") + on.exit(unlink(tempdir, recursive = TRUE), add = TRUE) + untar(destfile, exdir = tempdir) + pkgdir <- dir(tempdir, full.names = TRUE)[[1]] + + # Modify description + desc_path <- file.path(pkgdir, "DESCRIPTION") + desc_lines <- readLines(desc_path) + remotes_fields <- c( + "RemoteType: github", + "RemoteHost: api.github.com", + "RemoteRepo: renv", + "RemoteUsername: rstudio", + "RemotePkgRef: rstudio/renv", + paste("RemoteRef: ", sha), + paste("RemoteSha: ", sha) + ) + writeLines(c(desc_lines[desc_lines != ""], remotes_fields), con = desc_path) + + # Re-tar + local({ + old <- setwd(tempdir) + on.exit(setwd(old), add = TRUE) + + tar(destfile, compression = "gzip") + }) + invisible() + } + + # Extract the commit hash from a git archive. Git archives include the SHA1 + # hash as the comment field of the tarball pax extended header + # (see https://www.kernel.org/pub/software/scm/git/docs/git-archive.html) + # For GitHub archives this should be the first header after the default one + # (512 byte) header. + renv_bootstrap_git_extract_sha1_tar <- function(bundle) { + + # open the bundle for reading + # We use gzcon for everything because (from ?gzcon) + # > Reading from a connection which does not supply a 'gzip' magic + # > header is equivalent to reading from the original connection + conn <- gzcon(file(bundle, open = "rb", raw = TRUE)) + on.exit(close(conn)) + + # The default pax header is 512 bytes long and the first pax extended header + # with the comment should be 51 bytes long + # `52 comment=` (11 chars) + 40 byte SHA1 hash + len <- 0x200 + 0x33 + res <- rawToChar(readBin(conn, "raw", n = len)[0x201:len]) + + if (grepl("^52 comment=", res)) { + sub("52 comment=", "", res) + } else { + NULL + } + } + + renv_bootstrap_install <- function(version, tarball, library) { + + # attempt to install it into project library + dir.create(library, showWarnings = FALSE, recursive = TRUE) + output <- renv_bootstrap_install_impl(library, tarball) + + # check for successful install + status <- attr(output, "status") + if (is.null(status) || identical(status, 0L)) + return(status) + + # an error occurred; report it + header <- "installation of renv failed" + lines <- paste(rep.int("=", nchar(header)), collapse = "") + text <- paste(c(header, lines, output), collapse = "\n") + stop(text) + + } + + renv_bootstrap_install_impl <- function(library, tarball) { + + # invoke using system2 so we can capture and report output + bin <- R.home("bin") + exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" + R <- file.path(bin, exe) + + args <- c( + "--vanilla", "CMD", "INSTALL", "--no-multiarch", + "-l", shQuote(path.expand(library)), + shQuote(path.expand(tarball)) + ) + + system2(R, args, stdout = TRUE, stderr = TRUE) + + } + + renv_bootstrap_platform_prefix <- function() { + + # construct version prefix + version <- paste(R.version$major, R.version$minor, sep = ".") + prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-") + + # include SVN revision for development versions of R + # (to avoid sharing platform-specific artefacts with released versions of R) + devel <- + identical(R.version[["status"]], "Under development (unstable)") || + identical(R.version[["nickname"]], "Unsuffered Consequences") + + if (devel) + prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r") + + # build list of path components + components <- c(prefix, R.version$platform) + + # include prefix if provided by user + prefix <- renv_bootstrap_platform_prefix_impl() + if (!is.na(prefix) && nzchar(prefix)) + components <- c(prefix, components) + + # build prefix + paste(components, collapse = "/") + + } + + renv_bootstrap_platform_prefix_impl <- function() { + + # if an explicit prefix has been supplied, use it + prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA) + if (!is.na(prefix)) + return(prefix) + + # if the user has requested an automatic prefix, generate it + auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA) + if (is.na(auto) && getRversion() >= "4.4.0") + auto <- "TRUE" + + if (auto %in% c("TRUE", "True", "true", "1")) + return(renv_bootstrap_platform_prefix_auto()) + + # empty string on failure + "" + + } + + renv_bootstrap_platform_prefix_auto <- function() { + + prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity) + if (inherits(prefix, "error") || prefix %in% "unknown") { + + msg <- paste( + "failed to infer current operating system", + "please file a bug report at https://github.com/rstudio/renv/issues", + sep = "; " + ) + + warning(msg) + + } + + prefix + + } + + renv_bootstrap_platform_os <- function() { + + sysinfo <- Sys.info() + sysname <- sysinfo[["sysname"]] + + # handle Windows + macOS up front + if (sysname == "Windows") + return("windows") + else if (sysname == "Darwin") + return("macos") + + # check for os-release files + for (file in c("/etc/os-release", "/usr/lib/os-release")) + if (file.exists(file)) + return(renv_bootstrap_platform_os_via_os_release(file, sysinfo)) + + # check for redhat-release files + if (file.exists("/etc/redhat-release")) + return(renv_bootstrap_platform_os_via_redhat_release()) + + "unknown" + + } + + renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) { + + # read /etc/os-release + release <- utils::read.table( + file = file, + sep = "=", + quote = c("\"", "'"), + col.names = c("Key", "Value"), + comment.char = "#", + stringsAsFactors = FALSE + ) + + vars <- as.list(release$Value) + names(vars) <- release$Key + + # get os name + os <- tolower(sysinfo[["sysname"]]) + + # read id + id <- "unknown" + for (field in c("ID", "ID_LIKE")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + id <- vars[[field]] + break + } + } + + # read version + version <- "unknown" + for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + version <- vars[[field]] + break + } + } + + # join together + paste(c(os, id, version), collapse = "-") + + } + + renv_bootstrap_platform_os_via_redhat_release <- function() { + + # read /etc/redhat-release + contents <- readLines("/etc/redhat-release", warn = FALSE) + + # infer id + id <- if (grepl("centos", contents, ignore.case = TRUE)) + "centos" + else if (grepl("redhat", contents, ignore.case = TRUE)) + "redhat" + else + "unknown" + + # try to find a version component (very hacky) + version <- "unknown" + + parts <- strsplit(contents, "[[:space:]]")[[1L]] + for (part in parts) { + + nv <- tryCatch(numeric_version(part), error = identity) + if (inherits(nv, "error")) + next + + version <- nv[1, 1] + break + + } + + paste(c("linux", id, version), collapse = "-") + + } + + renv_bootstrap_library_root_name <- function(project) { + + # use project name as-is if requested + asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE") + if (asis) + return(basename(project)) + + # otherwise, disambiguate based on project's path + id <- substring(renv_bootstrap_hash_text(project), 1L, 8L) + paste(basename(project), id, sep = "-") + + } + + renv_bootstrap_library_root <- function(project) { + + prefix <- renv_bootstrap_profile_prefix() + + path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA) + if (!is.na(path)) + return(paste(c(path, prefix), collapse = "/")) + + path <- renv_bootstrap_library_root_impl(project) + if (!is.null(path)) { + name <- renv_bootstrap_library_root_name(project) + return(paste(c(path, prefix, name), collapse = "/")) + } + + renv_bootstrap_paths_renv("library", project = project) + + } + + renv_bootstrap_library_root_impl <- function(project) { + + root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA) + if (!is.na(root)) + return(root) + + type <- renv_bootstrap_project_type(project) + if (identical(type, "package")) { + userdir <- renv_bootstrap_user_dir() + return(file.path(userdir, "library")) + } + + } + + renv_bootstrap_validate_version <- function(version, description = NULL) { + + # resolve description file + # + # avoid passing lib.loc to `packageDescription()` below, since R will + # use the loaded version of the package by default anyhow. note that + # this function should only be called after 'renv' is loaded + # https://github.com/rstudio/renv/issues/1625 + description <- description %||% packageDescription("renv") + + # check whether requested version 'version' matches loaded version of renv + sha <- attr(version, "sha", exact = TRUE) + valid <- if (!is.null(sha)) + renv_bootstrap_validate_version_dev(sha, description) + else + renv_bootstrap_validate_version_release(version, description) + + if (valid) + return(TRUE) + + # the loaded version of renv doesn't match the requested version; + # give the user instructions on how to proceed + dev <- identical(description[["RemoteType"]], "github") + remote <- if (dev) + paste("rstudio/renv", description[["RemoteSha"]], sep = "@") + else + paste("renv", description[["Version"]], sep = "@") + + # display both loaded version + sha if available + friendly <- renv_bootstrap_version_friendly( + version = description[["Version"]], + sha = if (dev) description[["RemoteSha"]] + ) + + fmt <- heredoc(" + renv %1$s was loaded from project library, but this project is configured to use renv %2$s. + - Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile. + - Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library. + ") + catf(fmt, friendly, renv_bootstrap_version_friendly(version), remote) + + FALSE + + } + + renv_bootstrap_validate_version_dev <- function(version, description) { + expected <- description[["RemoteSha"]] + is.character(expected) && startswith(expected, version) + } + + renv_bootstrap_validate_version_release <- function(version, description) { + expected <- description[["Version"]] + is.character(expected) && identical(expected, version) + } + + renv_bootstrap_hash_text <- function(text) { + + hashfile <- tempfile("renv-hash-") + on.exit(unlink(hashfile), add = TRUE) + + writeLines(text, con = hashfile) + tools::md5sum(hashfile) + + } + + renv_bootstrap_load <- function(project, libpath, version) { + + # try to load renv from the project library + if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) + return(FALSE) + + # warn if the version of renv loaded does not match + renv_bootstrap_validate_version(version) + + # execute renv load hooks, if any + hooks <- getHook("renv::autoload") + for (hook in hooks) + if (is.function(hook)) + tryCatch(hook(), error = warnify) + + # load the project + renv::load(project) + + TRUE + + } + + renv_bootstrap_profile_load <- function(project) { + + # if RENV_PROFILE is already set, just use that + profile <- Sys.getenv("RENV_PROFILE", unset = NA) + if (!is.na(profile) && nzchar(profile)) + return(profile) + + # check for a profile file (nothing to do if it doesn't exist) + path <- renv_bootstrap_paths_renv("profile", profile = FALSE, project = project) + if (!file.exists(path)) + return(NULL) + + # read the profile, and set it if it exists + contents <- readLines(path, warn = FALSE) + if (length(contents) == 0L) + return(NULL) + + # set RENV_PROFILE + profile <- contents[[1L]] + if (!profile %in% c("", "default")) + Sys.setenv(RENV_PROFILE = profile) + + profile + + } + + renv_bootstrap_profile_prefix <- function() { + profile <- renv_bootstrap_profile_get() + if (!is.null(profile)) + return(file.path("profiles", profile, "renv")) + } + + renv_bootstrap_profile_get <- function() { + profile <- Sys.getenv("RENV_PROFILE", unset = "") + renv_bootstrap_profile_normalize(profile) + } + + renv_bootstrap_profile_set <- function(profile) { + profile <- renv_bootstrap_profile_normalize(profile) + if (is.null(profile)) + Sys.unsetenv("RENV_PROFILE") + else + Sys.setenv(RENV_PROFILE = profile) + } + + renv_bootstrap_profile_normalize <- function(profile) { + + if (is.null(profile) || profile %in% c("", "default")) + return(NULL) + + profile + + } + + renv_bootstrap_path_absolute <- function(path) { + + substr(path, 1L, 1L) %in% c("~", "/", "\\") || ( + substr(path, 1L, 1L) %in% c(letters, LETTERS) && + substr(path, 2L, 3L) %in% c(":/", ":\\") + ) + + } + + renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) { + renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv") + root <- if (renv_bootstrap_path_absolute(renv)) NULL else project + prefix <- if (profile) renv_bootstrap_profile_prefix() + components <- c(root, renv, prefix, ...) + paste(components, collapse = "/") + } + + renv_bootstrap_project_type <- function(path) { + + descpath <- file.path(path, "DESCRIPTION") + if (!file.exists(descpath)) + return("unknown") + + desc <- tryCatch( + read.dcf(descpath, all = TRUE), + error = identity + ) + + if (inherits(desc, "error")) + return("unknown") + + type <- desc$Type + if (!is.null(type)) + return(tolower(type)) + + package <- desc$Package + if (!is.null(package)) + return("package") + + "unknown" + + } + + renv_bootstrap_user_dir <- function() { + dir <- renv_bootstrap_user_dir_impl() + path.expand(chartr("\\", "/", dir)) + } + + renv_bootstrap_user_dir_impl <- function() { + + # use local override if set + override <- getOption("renv.userdir.override") + if (!is.null(override)) + return(override) + + # use R_user_dir if available + tools <- asNamespace("tools") + if (is.function(tools$R_user_dir)) + return(tools$R_user_dir("renv", "cache")) + + # try using our own backfill for older versions of R + envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME") + for (envvar in envvars) { + root <- Sys.getenv(envvar, unset = NA) + if (!is.na(root)) + return(file.path(root, "R/renv")) + } + + # use platform-specific default fallbacks + if (Sys.info()[["sysname"]] == "Windows") + file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv") + else if (Sys.info()[["sysname"]] == "Darwin") + "~/Library/Caches/org.R-project.R/R/renv" + else + "~/.cache/R/renv" + + } + + renv_bootstrap_version_friendly <- function(version, shafmt = NULL, sha = NULL) { + sha <- sha %||% attr(version, "sha", exact = TRUE) + parts <- c(version, sprintf(shafmt %||% " [sha: %s]", substring(sha, 1L, 7L))) + paste(parts, collapse = "") + } + + renv_bootstrap_exec <- function(project, libpath, version) { + if (!renv_bootstrap_load(project, libpath, version)) + renv_bootstrap_run(version, libpath) + } + + renv_bootstrap_run <- function(version, libpath) { + + # perform bootstrap + bootstrap(version, libpath) + + # exit early if we're just testing bootstrap + if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA))) + return(TRUE) + + # try again to load + if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { + return(renv::load(project = getwd())) + } + + # failed to download or load renv; warn the user + msg <- c( + "Failed to find an renv installation: the project will not be loaded.", + "Use `renv::activate()` to re-initialize the project." + ) + + warning(paste(msg, collapse = "\n"), call. = FALSE) + + } + + renv_json_read <- function(file = NULL, text = NULL) { + + jlerr <- NULL + + # if jsonlite is loaded, use that instead + if ("jsonlite" %in% loadedNamespaces()) { + + json <- tryCatch(renv_json_read_jsonlite(file, text), error = identity) + if (!inherits(json, "error")) + return(json) + + jlerr <- json + + } + + # otherwise, fall back to the default JSON reader + json <- tryCatch(renv_json_read_default(file, text), error = identity) + if (!inherits(json, "error")) + return(json) + + # report an error + if (!is.null(jlerr)) + stop(jlerr) + else + stop(json) + + } + + renv_json_read_jsonlite <- function(file = NULL, text = NULL) { + text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") + jsonlite::fromJSON(txt = text, simplifyVector = FALSE) + } + + renv_json_read_default <- function(file = NULL, text = NULL) { + + # find strings in the JSON + text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") + pattern <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + locs <- gregexpr(pattern, text, perl = TRUE)[[1]] + + # if any are found, replace them with placeholders + replaced <- text + strings <- character() + replacements <- character() + + if (!identical(c(locs), -1L)) { + + # get the string values + starts <- locs + ends <- locs + attr(locs, "match.length") - 1L + strings <- substring(text, starts, ends) + + # only keep those requiring escaping + strings <- grep("[[\\]{}:]", strings, perl = TRUE, value = TRUE) + + # compute replacements + replacements <- sprintf('"\032%i\032"', seq_along(strings)) + + # replace the strings + mapply(function(string, replacement) { + replaced <<- sub(string, replacement, replaced, fixed = TRUE) + }, strings, replacements) + + } + + # transform the JSON into something the R parser understands + transformed <- replaced + transformed <- gsub("{}", "`names<-`(list(), character())", transformed, fixed = TRUE) + transformed <- gsub("[[{]", "list(", transformed, perl = TRUE) + transformed <- gsub("[]}]", ")", transformed, perl = TRUE) + transformed <- gsub(":", "=", transformed, fixed = TRUE) + text <- paste(transformed, collapse = "\n") + + # parse it + json <- parse(text = text, keep.source = FALSE, srcfile = NULL)[[1L]] + + # construct map between source strings, replaced strings + map <- as.character(parse(text = strings)) + names(map) <- as.character(parse(text = replacements)) + + # convert to list + map <- as.list(map) + + # remap strings in object + remapped <- renv_json_read_remap(json, map) + + # evaluate + eval(remapped, envir = baseenv()) + + } + + renv_json_read_remap <- function(json, map) { + + # fix names + if (!is.null(names(json))) { + lhs <- match(names(json), names(map), nomatch = 0L) + rhs <- match(names(map), names(json), nomatch = 0L) + names(json)[rhs] <- map[lhs] + } + + # fix values + if (is.character(json)) + return(map[[json]] %||% json) + + # handle true, false, null + if (is.name(json)) { + text <- as.character(json) + if (text == "true") + return(TRUE) + else if (text == "false") + return(FALSE) + else if (text == "null") + return(NULL) + } + + # recurse + if (is.recursive(json)) { + for (i in seq_along(json)) { + json[i] <- list(renv_json_read_remap(json[[i]], map)) + } + } + + json + + } + + # load the renv profile, if any + renv_bootstrap_profile_load(project) + + # construct path to library root + root <- renv_bootstrap_library_root(project) + + # construct library prefix for platform + prefix <- renv_bootstrap_platform_prefix() + + # construct full libpath + libpath <- file.path(root, prefix) + + # run bootstrap code + renv_bootstrap_exec(project, libpath, version) + + invisible() + +}) diff --git a/blog/2026/property-values/renv/settings.json b/blog/2026/property-values/renv/settings.json new file mode 100644 index 0000000..ffdbb32 --- /dev/null +++ b/blog/2026/property-values/renv/settings.json @@ -0,0 +1,19 @@ +{ + "bioconductor.version": null, + "external.libraries": [], + "ignored.packages": [], + "package.dependency.fields": [ + "Imports", + "Depends", + "LinkingTo" + ], + "ppm.enabled": null, + "ppm.ignored.urls": [], + "r.version": null, + "snapshot.type": "implicit", + "use.cache": true, + "vcs.ignore.cellar": true, + "vcs.ignore.library": true, + "vcs.ignore.local": true, + "vcs.manage.ignores": true +} diff --git a/renv.lock b/renv.lock new file mode 100644 index 0000000..74d9ff7 --- /dev/null +++ b/renv.lock @@ -0,0 +1,2588 @@ +{ + "R": { + "Version": "4.5.2", + "Repositories": [ + { + "Name": "P3M", + "URL": "https://packagemanager.posit.co/cran/latest" + }, + { + "Name": "CRAN", + "URL": "https://cloud.r-project.org" + } + ] + }, + "Packages": { + "DBI": { + "Package": "DBI", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods" + ], + "Hash": "065ae649b05f1ff66bb0c793107508f5" + }, + "Formula": { + "Package": "Formula", + "Version": "1.2-5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "stats" + ], + "Hash": "7a29697b75e027767a53fde6c903eca7" + }, + "ISOcodes": { + "Package": "ISOcodes", + "Version": "2025.05.18", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "e15a512e4234d113186fb7c952641707" + }, + "KernSmooth": { + "Package": "KernSmooth", + "Version": "2.23-26", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "stats" + ], + "Hash": "2fb39782c07b5ad422b0448ae83f64c4" + }, + "MASS": { + "Package": "MASS", + "Version": "7.3-65", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "methods", + "stats", + "utils" + ], + "Hash": "a41d0fc833ea756a1136b60a437efe26" + }, + "R.methodsS3": { + "Package": "R.methodsS3", + "Version": "1.8.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "278c286fd6e9e75d0c2e8f731ea445c8" + }, + "R.oo": { + "Package": "R.oo", + "Version": "1.27.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R.methodsS3", + "methods", + "utils" + ], + "Hash": "a94afc14a90a68dd5043ceb9c089853b" + }, + "R.utils": { + "Package": "R.utils", + "Version": "2.13.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R.methodsS3", + "R.oo", + "methods", + "tools", + "utils" + ], + "Hash": "d32373d88da809f8974d5307481862b0" + }, + "R6": { + "Package": "R6", + "Version": "2.6.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "d4335fe7207f1c01ab8c41762f5840d4" + }, + "RColorBrewer": { + "Package": "RColorBrewer", + "Version": "1.1-3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "45f0398006e83a5b10b72a90663d8d8c" + }, + "Rcpp": { + "Package": "Rcpp", + "Version": "1.1.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods", + "utils" + ], + "Hash": "60df6f11cbeffbf9d50ad0852867f6b6" + }, + "S7": { + "Package": "S7", + "Version": "0.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "9da85950949574264f92f91f0e23de26" + }, + "V8": { + "Package": "V8", + "Version": "8.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp", + "curl", + "jsonlite", + "utils" + ], + "Hash": "f0301ca7b867eeb5c9b586a9e400729a" + }, + "askpass": { + "Package": "askpass", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "sys" + ], + "Hash": "c39f4155b3ceb1a9a2799d700fbd4b6a" + }, + "assertthat": { + "Package": "assertthat", + "Version": "0.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "tools" + ], + "Hash": "50c838a310445e954bc13f26f26a6ecf" + }, + "aws.s3": { + "Package": "aws.s3", + "Version": "0.3.22", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "aws.signature", + "base64enc", + "curl", + "digest", + "httr", + "tools", + "utils", + "xml2" + ], + "Hash": "cbb6690391d3ac39dfdfb4bff7250b4e" + }, + "aws.signature": { + "Package": "aws.signature", + "Version": "0.6.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "base64enc", + "digest" + ], + "Hash": "0006bcef272aad12f78dd5a85fc7f4fc" + }, + "backports": { + "Package": "backports", + "Version": "1.5.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "e1e1b9d75c37401117b636b7ae50827a" + }, + "base64enc": { + "Package": "base64enc", + "Version": "0.1-3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "543776ae6848fde2f48ff3816d0628bc" + }, + "bayestestR": { + "Package": "bayestestR", + "Version": "0.17.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "datawizard", + "graphics", + "insight", + "methods", + "stats", + "utils" + ], + "Hash": "06396210f1414b47a2702eb5d574934c" + }, + "bigD": { + "Package": "bigD", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "ad123ab90aa2fc795512f61ff6939c4a" + }, + "bit": { + "Package": "bit", + "Version": "4.6.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "ebe86ffd194564abdc895d87742d5a29" + }, + "bit64": { + "Package": "bit64", + "Version": "4.6.0-1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "bit", + "graphics", + "methods", + "stats", + "utils" + ], + "Hash": "4f572fbc586294afff277db583b9060f" + }, + "bitops": { + "Package": "bitops", + "Version": "1.0-9", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "d972ef991d58c19e6efa71b21f5e144b" + }, + "blob": { + "Package": "blob", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods", + "rlang", + "vctrs" + ], + "Hash": "1e0ae40898be928695fd90a80e816253" + }, + "broom": { + "Package": "broom", + "Version": "1.0.12", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "backports", + "cli", + "dplyr", + "generics", + "glue", + "lifecycle", + "purrr", + "rlang", + "stringr", + "tibble", + "tidyr" + ], + "Hash": "6cf2f6757591ea712c57c5d7bedc3c27" + }, + "bslib": { + "Package": "bslib", + "Version": "0.10.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "cachem", + "fastmap", + "grDevices", + "htmltools", + "jquerylib", + "jsonlite", + "lifecycle", + "memoise", + "mime", + "rlang", + "sass" + ], + "Hash": "d6072fb96c4868d8cb40d4071cdc472b" + }, + "cachem": { + "Package": "cachem", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "fastmap", + "rlang" + ], + "Hash": "cd9a672193789068eb5a2aad65a0dedf" + }, + "callr": { + "Package": "callr", + "Version": "3.7.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "processx", + "utils" + ], + "Hash": "d7e13f49c19103ece9e58ad2d83a7354" + }, + "cellranger": { + "Package": "cellranger", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "rematch", + "tibble" + ], + "Hash": "f61dbaec772ccd2e17705c1e872e9e7c" + }, + "checkmate": { + "Package": "checkmate", + "Version": "2.3.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "backports", + "utils" + ], + "Hash": "86cbe221fc19b56242f6c3eb0d4c5ab5" + }, + "class": { + "Package": "class", + "Version": "7.3-23", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "MASS", + "R", + "stats", + "utils" + ], + "Hash": "d0cb9cc838c3b43560bd958fc4317fdc" + }, + "classInt": { + "Package": "classInt", + "Version": "0.4-11", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "KernSmooth", + "R", + "class", + "e1071", + "grDevices", + "graphics", + "stats" + ], + "Hash": "f2af70314a63d7f025ae668f08bd933a" + }, + "cli": { + "Package": "cli", + "Version": "3.6.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "16850760556401a2eeb27d39bd11c9cb" + }, + "clipr": { + "Package": "clipr", + "Version": "0.8.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "utils" + ], + "Hash": "3f038e5ac7f41d4ac41ce658c85e3042" + }, + "commonmark": { + "Package": "commonmark", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "8cba62334c1088d21689d353a7e87663" + }, + "conflicted": { + "Package": "conflicted", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "memoise", + "rlang" + ], + "Hash": "bb097fccb22d156624fd07cd2894ddb6" + }, + "cpp11": { + "Package": "cpp11", + "Version": "0.5.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "af5958631ca49510aff96d0f5c0bbb76" + }, + "crayon": { + "Package": "crayon", + "Version": "1.5.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "grDevices", + "methods", + "utils" + ], + "Hash": "859d96e65ef198fd43e82b9628d593ef" + }, + "crosstalk": { + "Package": "crosstalk", + "Version": "1.2.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R6", + "htmltools", + "jsonlite", + "lazyeval" + ], + "Hash": "8b008bc619e0bbebb5646b3d37efdad1" + }, + "crul": { + "Package": "crul", + "Version": "1.6.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R6", + "curl", + "httpcode", + "jsonlite", + "lifecycle", + "mime", + "rlang", + "urltools" + ], + "Hash": "3aeb4061f5f9c25b3621a14c8e024a48" + }, + "curl": { + "Package": "curl", + "Version": "7.0.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "aa27e963d3deccf4bade44d06b976977" + }, + "data.table": { + "Package": "data.table", + "Version": "1.18.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "df99cd4333ce592df5173d6ad39b5c14" + }, + "datawizard": { + "Package": "datawizard", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "insight", + "stats", + "utils" + ], + "Hash": "6acfecf3792005ee2e2e1eb7ede6c1c1" + }, + "dbplyr": { + "Package": "dbplyr", + "Version": "2.5.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "DBI", + "R", + "R6", + "blob", + "cli", + "dplyr", + "glue", + "lifecycle", + "magrittr", + "methods", + "pillar", + "purrr", + "rlang", + "tibble", + "tidyr", + "tidyselect", + "utils", + "vctrs", + "withr" + ], + "Hash": "e38d7151c767b00b919091be4686e274" + }, + "digest": { + "Package": "digest", + "Version": "0.6.39", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "d18028e978a88b2b16ef8d400cb49adf" + }, + "dplyr": { + "Package": "dplyr", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "cli", + "generics", + "glue", + "lifecycle", + "magrittr", + "methods", + "pillar", + "rlang", + "tibble", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "fedd9d00c2944ff00a0e2696ccf048ec" + }, + "dreamerr": { + "Package": "dreamerr", + "Version": "1.5.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Formula", + "stringmagic", + "utils" + ], + "Hash": "f2e4bf22bbf86fb1eca4fd252901e23c" + }, + "dtplyr": { + "Package": "dtplyr", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "data.table", + "dplyr", + "glue", + "lifecycle", + "rlang", + "tibble", + "tidyselect", + "vctrs" + ], + "Hash": "50bbedd3d5b6a4ddc3c3c1602456aa35" + }, + "e1071": { + "Package": "e1071", + "Version": "1.7-17", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "class", + "grDevices", + "graphics", + "methods", + "proxy", + "stats", + "utils" + ], + "Hash": "9d516dde384526d4784166f888cd2c6c" + }, + "evaluate": { + "Package": "evaluate", + "Version": "1.0.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "94cf2c54237f6841cee68e3ba4ab5a14" + }, + "farver": { + "Package": "farver", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "P3M", + "Hash": "680887028577f3fa2a81e410ed0d6e42" + }, + "fastmap": { + "Package": "fastmap", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "P3M", + "Hash": "aa5e1cd11c2d15497494c5292d7ffcc8" + }, + "fixest": { + "Package": "fixest", + "Version": "0.13.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "dreamerr", + "grDevices", + "graphics", + "methods", + "nlme", + "numDeriv", + "sandwich", + "stats", + "stringmagic", + "tools", + "utils" + ], + "Hash": "f33d6987967224b1e60d29d26907f28a" + }, + "fontawesome": { + "Package": "fontawesome", + "Version": "0.5.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "htmltools", + "rlang" + ], + "Hash": "bd1297f9b5b1fc1372d19e2c4cd82215" + }, + "forcats": { + "Package": "forcats", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "tibble" + ], + "Hash": "f884a14605c6a9eb01db676eee793ba7" + }, + "fs": { + "Package": "fs", + "Version": "1.6.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods" + ], + "Hash": "7eb1e342eee7e0a7449c49cdaa526d39" + }, + "gargle": { + "Package": "gargle", + "Version": "1.6.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "fs", + "glue", + "httr", + "jsonlite", + "lifecycle", + "openssl", + "rappdirs", + "rlang", + "stats", + "utils", + "withr" + ], + "Hash": "99e4f3f00be5075372bb650a3e237a71" + }, + "generics": { + "Package": "generics", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods" + ], + "Hash": "4b29bf698d0c7bdb9f1e4976e7ade41d" + }, + "geodist": { + "Package": "geodist", + "Version": "0.1.1", + "Source": "Repository", + "Repository": "P3M", + "Hash": "061a2a4bfa62f488c9d73a35b9fd2939" + }, + "geojson": { + "Package": "geojson", + "Version": "0.3.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "jqr", + "jsonlite", + "lazyeval", + "magrittr", + "methods", + "protolite", + "sp" + ], + "Hash": "efc8d020709d1e1f9628a8d5362d193b" + }, + "geojsonio": { + "Package": "geojsonio", + "Version": "0.11.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "V8", + "crul", + "geojson", + "geojsonsf", + "jqr", + "jsonlite", + "magrittr", + "methods", + "readr", + "sf", + "sp" + ], + "Hash": "f0424e67a22ce09aaf89d6bc2b7f9431" + }, + "geojsonsf": { + "Package": "geojsonsf", + "Version": "2.0.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "geometries", + "jsonify", + "rapidjsonr", + "sfheaders" + ], + "Hash": "3096b36cc9ab822560d3217c068e4641" + }, + "geometries": { + "Package": "geometries", + "Version": "0.2.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp" + ], + "Hash": "cb7b9ad43bcf8d06d5c652f510ff5509" + }, + "gganimate": { + "Package": "gganimate", + "Version": "1.0.11", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "cli", + "ggplot2", + "glue", + "grDevices", + "grid", + "lifecycle", + "progress", + "rlang", + "scales", + "stringi", + "transformr", + "tweenr", + "utils", + "vctrs" + ], + "Hash": "867678fc40cb2db65e5ca7a5ea4d628d" + }, + "ggplot2": { + "Package": "ggplot2", + "Version": "4.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "S7", + "cli", + "grDevices", + "grid", + "gtable", + "isoband", + "lifecycle", + "rlang", + "scales", + "stats", + "vctrs", + "withr" + ], + "Hash": "1bfa14b2a1668b3569dafb0478b2636b" + }, + "glue": { + "Package": "glue", + "Version": "1.8.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods" + ], + "Hash": "5899f1eaa825580172bb56c08266f37c" + }, + "googledrive": { + "Package": "googledrive", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "gargle", + "glue", + "httr", + "jsonlite", + "lifecycle", + "magrittr", + "pillar", + "purrr", + "rlang", + "tibble", + "utils", + "uuid", + "vctrs", + "withr" + ], + "Hash": "292be194aa519482c4b83f488a818ba3" + }, + "googlesheets4": { + "Package": "googlesheets4", + "Version": "1.1.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cellranger", + "cli", + "curl", + "gargle", + "glue", + "googledrive", + "httr", + "ids", + "lifecycle", + "magrittr", + "methods", + "purrr", + "rematch2", + "rlang", + "tibble", + "utils", + "vctrs", + "withr" + ], + "Hash": "376adbf359b416dbb30a76a2d2051ed5" + }, + "gt": { + "Package": "gt", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "bigD", + "bitops", + "cli", + "commonmark", + "dplyr", + "fs", + "glue", + "htmltools", + "htmlwidgets", + "juicyjuice", + "magrittr", + "markdown", + "reactable", + "rlang", + "sass", + "scales", + "tidyselect", + "vctrs", + "xml2" + ], + "Hash": "7153ac3985ed54f1a318590b73950329" + }, + "gtable": { + "Package": "gtable", + "Version": "0.3.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "glue", + "grid", + "lifecycle", + "rlang", + "stats" + ], + "Hash": "de949855009e2d4d0e52a844e30617ae" + }, + "gtfsio": { + "Package": "gtfsio", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "data.table", + "fs", + "jsonlite", + "utils", + "zip" + ], + "Hash": "c88ef74fb18827ab67963a8a4d52304c" + }, + "haven": { + "Package": "haven", + "Version": "2.5.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "cpp11", + "forcats", + "hms", + "lifecycle", + "methods", + "readr", + "rlang", + "tibble", + "tidyselect", + "vctrs" + ], + "Hash": "437bc7804f8ffdfcfed38d0aead6a9d7" + }, + "here": { + "Package": "here", + "Version": "1.0.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "rprojroot" + ], + "Hash": "e5114f2abe04168238181913a8572358" + }, + "highr": { + "Package": "highr", + "Version": "0.11", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "xfun" + ], + "Hash": "d65ba49117ca223614f71b60d85b8ab7" + }, + "hms": { + "Package": "hms", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "cli", + "lifecycle", + "methods", + "pkgconfig", + "rlang", + "vctrs" + ], + "Hash": "2799ac720626cec589478b191e48b88b" + }, + "htmltools": { + "Package": "htmltools", + "Version": "0.5.9", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "base64enc", + "digest", + "fastmap", + "grDevices", + "rlang", + "utils" + ], + "Hash": "102298e238c14eb830cc4b5edd23c3e8" + }, + "htmlwidgets": { + "Package": "htmlwidgets", + "Version": "1.6.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "grDevices", + "htmltools", + "jsonlite", + "knitr", + "rmarkdown", + "yaml" + ], + "Hash": "04291cc45198225444a397606810ac37" + }, + "httpcode": { + "Package": "httpcode", + "Version": "0.3.0", + "Source": "Repository", + "Repository": "P3M", + "Hash": "13641a1c6d2cc98801b76764078e17ea" + }, + "httr": { + "Package": "httr", + "Version": "1.4.7", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "curl", + "jsonlite", + "mime", + "openssl" + ], + "Hash": "ac107251d9d9fd72f0ca8049988f1d7f" + }, + "ids": { + "Package": "ids", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "openssl", + "uuid" + ], + "Hash": "99df65cfef20e525ed38c3d2577f7190" + }, + "insight": { + "Package": "insight", + "Version": "1.4.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods", + "stats", + "utils" + ], + "Hash": "c3c6595dfc27f57a0031a6548076e0d8" + }, + "isoband": { + "Package": "isoband", + "Version": "0.3.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "cli", + "cpp11", + "grid", + "rlang", + "utils" + ], + "Hash": "0f9a864bbd7ce0232ad05cb76249cc1a" + }, + "jpeg": { + "Package": "jpeg", + "Version": "0.1-11", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "c23ab23c370d1ce3a7a80d8c0bdfa105" + }, + "jqr": { + "Package": "jqr", + "Version": "1.4.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "lazyeval", + "magrittr" + ], + "Hash": "25aad95d788314e4b307ead16059288d" + }, + "jquerylib": { + "Package": "jquerylib", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "htmltools" + ], + "Hash": "5aab57a3bd297eee1c1d862735972182" + }, + "jsonify": { + "Package": "jsonify", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "rapidjsonr" + ], + "Hash": "5edb07a22dcc39e90c2b4a761f9b39db" + }, + "jsonlite": { + "Package": "jsonlite", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "methods" + ], + "Hash": "b0776f526d36d8bd4a3344a88fe165c4" + }, + "juicyjuice": { + "Package": "juicyjuice", + "Version": "0.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "V8" + ], + "Hash": "3bcd11943da509341838da9399e18bce" + }, + "knitr": { + "Package": "knitr", + "Version": "1.51", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "evaluate", + "highr", + "methods", + "tools", + "xfun", + "yaml" + ], + "Hash": "27682babb50f03b6eb7939ea69ec79ca" + }, + "labeling": { + "Package": "labeling", + "Version": "0.4.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "graphics", + "stats" + ], + "Hash": "b64ec208ac5bc1852b285f665d6368b3" + }, + "lattice": { + "Package": "lattice", + "Version": "0.22-7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "grid", + "stats", + "utils" + ], + "Hash": "934f30aea6442867f57a610034ab06d3" + }, + "lazyeval": { + "Package": "lazyeval", + "Version": "0.2.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "d908914ae53b04d4c0c0fd72ecc35370" + }, + "leaflet": { + "Package": "leaflet", + "Version": "2.2.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "RColorBrewer", + "crosstalk", + "htmltools", + "htmlwidgets", + "jquerylib", + "leaflet.providers", + "magrittr", + "methods", + "png", + "raster", + "rlang", + "scales", + "sf", + "stats", + "viridisLite", + "xfun" + ], + "Hash": "da8aa03b2885c2b934923e6a53fe592a" + }, + "leaflet.providers": { + "Package": "leaflet.providers", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "htmltools" + ], + "Hash": "c0b81ad9d5d932772f7a457ac398cf36" + }, + "lifecycle": { + "Package": "lifecycle", + "Version": "1.0.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "rlang" + ], + "Hash": "36dbfe4fba6c064db50a671a90297c85" + }, + "litedown": { + "Package": "litedown", + "Version": "0.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "commonmark", + "utils", + "xfun" + ], + "Hash": "6b9435273e6506fbafa5909adf4abb88" + }, + "lpSolve": { + "Package": "lpSolve", + "Version": "5.6.23", + "Source": "Repository", + "Repository": "P3M", + "Hash": "c4e64e374c4ab1e6ffda55073fd04c59" + }, + "lubridate": { + "Package": "lubridate", + "Version": "1.9.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "generics", + "methods", + "timechange" + ], + "Hash": "be38bc740fc51783a78edb5a157e4104" + }, + "magick": { + "Package": "magick", + "Version": "2.9.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "curl", + "magrittr" + ], + "Hash": "8b43f0e49eb9585e9e7faf12145ee79e" + }, + "magrittr": { + "Package": "magrittr", + "Version": "2.0.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "8b3b213aa0c54a0dec254288ccb545d1" + }, + "mapboxapi": { + "Package": "mapboxapi", + "Version": "0.6.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "aws.s3", + "curl", + "dplyr", + "geojsonsf", + "htmltools", + "httr", + "jpeg", + "jsonlite", + "leaflet", + "magick", + "png", + "protolite", + "purrr", + "raster", + "rlang", + "sf", + "slippymath", + "stringi", + "tidyr", + "units" + ], + "Hash": "8a8f8bcb89ca75e45b22e7ee88e211de" + }, + "marginaleffects": { + "Package": "marginaleffects", + "Version": "0.32.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Formula", + "R", + "backports", + "checkmate", + "data.table", + "generics", + "insight", + "methods", + "rlang" + ], + "Hash": "fecb96ffc7d24ec956a4ff4980264952" + }, + "markdown": { + "Package": "markdown", + "Version": "2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "litedown", + "utils", + "xfun" + ], + "Hash": "b4349847250b103bbbb8bc6819c4fbca" + }, + "memoise": { + "Package": "memoise", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "cachem", + "rlang" + ], + "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c" + }, + "mime": { + "Package": "mime", + "Version": "0.13", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "tools" + ], + "Hash": "0ec19f34c72fab674d8f2b4b1c6410e1" + }, + "modelr": { + "Package": "modelr", + "Version": "0.1.11", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "broom", + "magrittr", + "purrr", + "rlang", + "tibble", + "tidyr", + "tidyselect", + "vctrs" + ], + "Hash": "4f50122dc256b1b6996a4703fecea821" + }, + "modelsummary": { + "Package": "modelsummary", + "Version": "2.6.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "checkmate", + "data.table", + "generics", + "glue", + "insight", + "methods", + "parameters", + "performance", + "tables", + "tinytable" + ], + "Hash": "300c51ccba8888aa7d24b55bf726228e" + }, + "mountainmathHelpers": { + "Package": "mountainmathHelpers", + "Version": "0.1.4", + "Source": "GitHub", + "RemoteType": "github", + "RemoteHost": "api.github.com", + "RemoteUsername": "mountainmath", + "RemoteRepo": "mountainmathhelpers", + "RemoteRef": "master", + "RemoteSha": "6af7c868601c9c7434f01169bfbe7c4b3636fd9c", + "Requirements": [ + "R.utils", + "aws.s3", + "digest", + "dplyr", + "geojsonsf", + "ggplot2", + "httr", + "jsonlite", + "mapboxapi", + "readr", + "rlang", + "rmapzen", + "sf", + "slippymath" + ], + "Hash": "cea5db1c698d774b09c94885abd84403" + }, + "nlme": { + "Package": "nlme", + "Version": "3.1-168", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "graphics", + "lattice", + "stats", + "utils" + ], + "Hash": "b1d2ea08d5d392831fbc32c872362b06" + }, + "numDeriv": { + "Package": "numDeriv", + "Version": "2016.8-1.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "df58958f293b166e4ab885ebcad90e02" + }, + "openssl": { + "Package": "openssl", + "Version": "2.3.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "askpass" + ], + "Hash": "d5811dade9cd3a34a9038a45f1a59bae" + }, + "parameters": { + "Package": "parameters", + "Version": "0.28.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "bayestestR", + "datawizard", + "graphics", + "insight", + "methods", + "stats", + "utils" + ], + "Hash": "5c812a68308c47fa9cafbfebccc3e356" + }, + "performance": { + "Package": "performance", + "Version": "0.16.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "bayestestR", + "datawizard", + "insight", + "methods", + "stats", + "utils" + ], + "Hash": "d02d66e01f1d11197809c79bb19d628f" + }, + "pillar": { + "Package": "pillar", + "Version": "1.11.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "cli", + "glue", + "lifecycle", + "rlang", + "utf8", + "utils", + "vctrs" + ], + "Hash": "1395e64f2689ffd503657778e810cee2" + }, + "pkgconfig": { + "Package": "pkgconfig", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "utils" + ], + "Hash": "01f28d4278f15c76cddbea05899c5d6f" + }, + "png": { + "Package": "png", + "Version": "0.1-8", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "bd54ba8a0a5faded999a7aab6e46b374" + }, + "prettyunits": { + "Package": "prettyunits", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "6b01fc98b1e86c4f705ce9dcfd2f57c7" + }, + "processx": { + "Package": "processx", + "Version": "3.8.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "ps", + "utils" + ], + "Hash": "720161b280b0a35f4d1490ead2fe81d0" + }, + "progress": { + "Package": "progress", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "crayon", + "hms", + "prettyunits" + ], + "Hash": "f4625e061cb2865f111b47ff163a5ca6" + }, + "protolite": { + "Package": "protolite", + "Version": "2.3.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp", + "jsonlite" + ], + "Hash": "ea2364e73971f7e570bffc59868e3912" + }, + "proxy": { + "Package": "proxy", + "Version": "0.4-29", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "stats", + "utils" + ], + "Hash": "b6c826e897b46b163c51a3b990113a21" + }, + "ps": { + "Package": "ps", + "Version": "1.9.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "093688087b0bacce6ba2f661f36328e2" + }, + "purrr": { + "Package": "purrr", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "lifecycle", + "magrittr", + "rlang", + "vctrs" + ], + "Hash": "0154ac5b9ef4df1a7be3a54602e781cf" + }, + "ragg": { + "Package": "ragg", + "Version": "1.5.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "systemfonts", + "textshaping" + ], + "Hash": "cdb40b21711a8870f305b24226698f9f" + }, + "rapidjsonr": { + "Package": "rapidjsonr", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "P3M", + "Hash": "b6a97237ee07c7fcfe836f1b6ba882b0" + }, + "rappdirs": { + "Package": "rappdirs", + "Version": "0.3.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "f146a5bfc94db048309712535d4d0aee" + }, + "raster": { + "Package": "raster", + "Version": "3.6-32", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "methods", + "sp", + "terra" + ], + "Hash": "1e193fc2c727a6f83cf95d9e16024423" + }, + "reactR": { + "Package": "reactR", + "Version": "0.6.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "htmltools" + ], + "Hash": "b8e3d93f508045812f47136c7c44c251" + }, + "reactable": { + "Package": "reactable", + "Version": "0.4.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "digest", + "htmltools", + "htmlwidgets", + "jsonlite", + "reactR" + ], + "Hash": "abfd6fa3794ff78116123d95845e0c32" + }, + "readr": { + "Package": "readr", + "Version": "2.1.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "cli", + "clipr", + "cpp11", + "crayon", + "hms", + "lifecycle", + "methods", + "rlang", + "tibble", + "tzdb", + "utils", + "vroom" + ], + "Hash": "141ebcec1bf55707751c7956a34d93db" + }, + "readxl": { + "Package": "readxl", + "Version": "1.4.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cellranger", + "cpp11", + "progress", + "tibble", + "utils" + ], + "Hash": "18948de59f05d38a44d3e5065a76b4b6" + }, + "rematch": { + "Package": "rematch", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "P3M", + "Hash": "cbff1b666c6fa6d21202f07e2318d4f1" + }, + "rematch2": { + "Package": "rematch2", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "tibble" + ], + "Hash": "76c9e04c712a05848ae7a23d2f170a40" + }, + "renv": { + "Package": "renv", + "Version": "1.0.11", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "utils" + ], + "Hash": "47623f66b4e80b3b0587bc5d7b309888" + }, + "reprex": { + "Package": "reprex", + "Version": "2.1.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "callr", + "cli", + "clipr", + "fs", + "glue", + "knitr", + "lifecycle", + "rlang", + "rmarkdown", + "rstudioapi", + "utils", + "withr" + ], + "Hash": "97b1d5361a24d9fb588db7afe3e5bcbf" + }, + "rlang": { + "Package": "rlang", + "Version": "1.1.7", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "34c0d101f4613098abc538b82e0d86c5" + }, + "rmapzen": { + "Package": "rmapzen", + "Version": "0.5.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "ISOcodes", + "R", + "assertthat", + "digest", + "dplyr", + "geojsonio", + "httr", + "jsonlite", + "purrr", + "sf", + "tibble", + "tidyr", + "utils" + ], + "Hash": "5f2da6eb8d2ea66342ea0799b37fb802" + }, + "rmarkdown": { + "Package": "rmarkdown", + "Version": "2.30", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "bslib", + "evaluate", + "fontawesome", + "htmltools", + "jquerylib", + "jsonlite", + "knitr", + "methods", + "tinytex", + "tools", + "utils", + "xfun", + "yaml" + ], + "Hash": "efe19db0fde0fff13cea7eec6f695021" + }, + "rprojroot": { + "Package": "rprojroot", + "Version": "2.1.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "b2453de2d29aa646afe4781defdc7903" + }, + "rstudioapi": { + "Package": "rstudioapi", + "Version": "0.18.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "d6e1ecf8e39b6d53c8acde372b2f92d1" + }, + "rvest": { + "Package": "rvest", + "Version": "1.0.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "glue", + "httr", + "lifecycle", + "magrittr", + "rlang", + "selectr", + "tibble", + "xml2" + ], + "Hash": "2804ddcd7737082306c559d919886546" + }, + "s2": { + "Package": "s2", + "Version": "1.1.9", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "wk" + ], + "Hash": "4e664a5d610d58f27ec196e96cdb7f6f" + }, + "sandwich": { + "Package": "sandwich", + "Version": "3.1-1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "stats", + "utils", + "zoo" + ], + "Hash": "072bb2d27425f2a58fe71fe1080676ce" + }, + "sass": { + "Package": "sass", + "Version": "0.4.10", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R6", + "fs", + "htmltools", + "rappdirs", + "rlang" + ], + "Hash": "3fb78d066fb92299b1d13f6a7c9a90a8" + }, + "scales": { + "Package": "scales", + "Version": "1.4.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "RColorBrewer", + "cli", + "farver", + "glue", + "labeling", + "lifecycle", + "rlang", + "viridisLite" + ], + "Hash": "c5bba8f0d1df8c4b9538a40570798d9b" + }, + "selectr": { + "Package": "selectr", + "Version": "0.5-1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "methods", + "stringr" + ], + "Hash": "fb6f4aacfcc16539458c66b698339e69" + }, + "sf": { + "Package": "sf", + "Version": "1.0-24", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "DBI", + "R", + "Rcpp", + "classInt", + "grDevices", + "graphics", + "grid", + "magrittr", + "methods", + "s2", + "stats", + "tools", + "units", + "utils" + ], + "Hash": "7a4756aedf70812aa33fba3d29529424" + }, + "sfheaders": { + "Package": "sfheaders", + "Version": "0.4.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "geometries" + ], + "Hash": "c655cae84ce671c8aa1067cbf2ff0fe4" + }, + "slippymath": { + "Package": "slippymath", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "png", + "purrr", + "raster", + "stats" + ], + "Hash": "abdaf883004a4791545655d79ca3aae0" + }, + "sp": { + "Package": "sp", + "Version": "2.2-0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "grDevices", + "graphics", + "grid", + "lattice", + "methods", + "stats", + "utils" + ], + "Hash": "d9ff3b753db98bc50650314c8782abe6" + }, + "stringi": { + "Package": "stringi", + "Version": "1.8.7", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "stats", + "tools", + "utils" + ], + "Hash": "2b56088e23bdd58f89aebf43a0913457" + }, + "stringmagic": { + "Package": "stringmagic", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp", + "stats", + "utils" + ], + "Hash": "b972dfa36bb17a053cb5a21c1b3edc0f" + }, + "stringr": { + "Package": "stringr", + "Version": "1.6.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "stringi", + "vctrs" + ], + "Hash": "d47392652eedc68bf916657347ff2526" + }, + "sys": { + "Package": "sys", + "Version": "3.4.3", + "Source": "Repository", + "Repository": "P3M", + "Hash": "de342ebfebdbf40477d0758d05426646" + }, + "systemfonts": { + "Package": "systemfonts", + "Version": "1.3.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "base64enc", + "cpp11", + "grid", + "jsonlite", + "lifecycle", + "tools", + "utils" + ], + "Hash": "4fae513a3bb1a155943d1e9d1ae467ec" + }, + "tables": { + "Package": "tables", + "Version": "0.9.33", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "htmltools", + "knitr", + "stats", + "utils" + ], + "Hash": "fe19a0ed754e2ab39f85bac09f5f01cc" + }, + "terra": { + "Package": "terra", + "Version": "1.8-93", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "methods" + ], + "Hash": "bb3e2b0e01eeeed8c3e828faaf6c68b5" + }, + "textshaping": { + "Package": "textshaping", + "Version": "1.0.4", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cpp11", + "lifecycle", + "stats", + "stringi", + "systemfonts", + "utils" + ], + "Hash": "477d70e23914730aa7f5c5fd351f4721" + }, + "tibble": { + "Package": "tibble", + "Version": "3.3.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "lifecycle", + "magrittr", + "methods", + "pillar", + "pkgconfig", + "rlang", + "utils", + "vctrs" + ], + "Hash": "c55df870972551cac674b50cadb2d51f" + }, + "tidyr": { + "Package": "tidyr", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "cpp11", + "dplyr", + "glue", + "lifecycle", + "magrittr", + "purrr", + "rlang", + "stringr", + "tibble", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "a4fa2f5876396f04814cb9d8d9ab89e9" + }, + "tidyselect": { + "Package": "tidyselect", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang", + "vctrs", + "withr" + ], + "Hash": "829f27b9c4919c16b593794a6344d6c0" + }, + "tidytransit": { + "Package": "tidytransit", + "Version": "1.8.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "data.table", + "digest", + "dplyr", + "geodist", + "gtfsio", + "hms", + "jsonlite", + "sf" + ], + "Hash": "e9781c32fd604605bb307e4638e0ed00" + }, + "tidyverse": { + "Package": "tidyverse", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "broom", + "cli", + "conflicted", + "dbplyr", + "dplyr", + "dtplyr", + "forcats", + "ggplot2", + "googledrive", + "googlesheets4", + "haven", + "hms", + "httr", + "jsonlite", + "lubridate", + "magrittr", + "modelr", + "pillar", + "purrr", + "ragg", + "readr", + "readxl", + "reprex", + "rlang", + "rstudioapi", + "rvest", + "stringr", + "tibble", + "tidyr", + "xml2" + ], + "Hash": "c328568cd14ea89a83bd4ca7f54ae07e" + }, + "timechange": { + "Package": "timechange", + "Version": "0.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "39c40cb1ad47a4cc384a34a22a29463f" + }, + "tinytable": { + "Package": "tinytable", + "Version": "0.16.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "methods" + ], + "Hash": "c2e748cbeefd0ca50d5eafc056250f26" + }, + "tinytex": { + "Package": "tinytex", + "Version": "0.58", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "xfun" + ], + "Hash": "03af3ad04817f3019de8ee5c73dab807" + }, + "transformr": { + "Package": "transformr", + "Version": "0.1.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "cpp11", + "lpSolve", + "rlang", + "sf", + "tweenr", + "vctrs" + ], + "Hash": "584eda9966ed571b3adc75e338116147" + }, + "triebeard": { + "Package": "triebeard", + "Version": "0.4.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp" + ], + "Hash": "642507a148b0dd9b5620177e0a044413" + }, + "tweenr": { + "Package": "tweenr", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cpp11", + "farver", + "magrittr", + "rlang", + "vctrs" + ], + "Hash": "82fac2b73e6a1f3874fc000aaf96d8bc" + }, + "tzdb": { + "Package": "tzdb", + "Version": "0.5.0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "09e3961e87b7bafa4a9340bbb34aeda8" + }, + "units": { + "Package": "units", + "Version": "1.0-0", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp" + ], + "Hash": "3797c73fd3bde8b1601a4e1bf53557ac" + }, + "urltools": { + "Package": "urltools", + "Version": "1.7.3.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "Rcpp", + "methods", + "triebeard" + ], + "Hash": "0951eeef49e3df040dfc67ce75a052ac" + }, + "utf8": { + "Package": "utf8", + "Version": "1.2.6", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "d526d558be176e9ceb68c3d1e83479b7" + }, + "uuid": { + "Package": "uuid", + "Version": "1.2-2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "528fc9e90d70a6a115e21164f37b2c64" + }, + "vctrs": { + "Package": "vctrs", + "Version": "0.7.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang" + ], + "Hash": "c64e64d93489bb62bb8747bbb9e06c09" + }, + "viridisLite": { + "Package": "viridisLite", + "Version": "0.4.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "c826c7c4241b6fc89ff55aaea3fa7491" + }, + "vroom": { + "Package": "vroom", + "Version": "1.7.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bit64", + "cli", + "cpp11", + "crayon", + "glue", + "hms", + "lifecycle", + "methods", + "progress", + "rlang", + "stats", + "tibble", + "tidyselect", + "tzdb", + "vctrs", + "withr" + ], + "Hash": "255cb6f090718455ff89cbc28cb5eea7" + }, + "withr": { + "Package": "withr", + "Version": "3.0.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "grDevices", + "graphics" + ], + "Hash": "cc2d62c76458d425210d1eb1478b30b4" + }, + "wk": { + "Package": "wk", + "Version": "0.9.5", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "10fb21ed42dbd4ed9162aaab818146e3" + }, + "xfun": { + "Package": "xfun", + "Version": "0.56", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "stats", + "tools" + ], + "Hash": "f1f18d352a39c6252932da4faa029cdd" + }, + "xml2": { + "Package": "xml2", + "Version": "1.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "methods", + "rlang" + ], + "Hash": "d8e98d08a4a4d03f5052acc6e6204b99" + }, + "yaml": { + "Package": "yaml", + "Version": "2.3.12", + "Source": "Repository", + "Repository": "P3M", + "Hash": "7cd77cb32abd9220d744307e9fc94ffb" + }, + "zip": { + "Package": "zip", + "Version": "2.3.3", + "Source": "Repository", + "Repository": "P3M", + "Hash": "6ebe4b1dc74c3e50e74e316323629583" + }, + "zoo": { + "Package": "zoo", + "Version": "1.8-15", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "grDevices", + "graphics", + "lattice", + "stats", + "utils" + ], + "Hash": "3f85ec88dadbaa3301917cea59727329" + } + } +}