When duckdb meets dplyr!

R
DuckDB
dplyr
duckplyr
S3
Parquet
Author

Philippe Massicotte

Published

May 1, 2024

Introduction

I like DuckDB πŸ¦†. I am excited to see that it is now possible to use it with dplyr using the fantastic duckplyr package which gives us another way to bridge dplyr with DuckDB.

When duckdb meets dplyr! Photo by DuckDB

When duckdb meets dplyr! Photo by DuckDB

In this short post, I will show how duckplyr can be used to query parquet files hosted on an S3 bucket. I will use the duckplyr_df_from_parquet() function to read the data and then use dplyr verbs to summarize the data.

First, let’s install the duckplyr package and load the necessary libraries.

install.packages("duckplyr")
library(dplyr)
library(duckplyr)
library(duckdb)

options(duckdb.materialize_message = FALSE)

In order we need to follow these steps:

  1. Create a connection to a DuckDB database.
  2. Load the httpfs extension.
  3. Set the S3 region and endpoint to access the data.
con <- duckplyr:::get_default_duckdb_connection()

DBI::dbSendQuery(con, "INSTALL httpfs; LOAD httpfs;")
DBI::dbSendQuery(
  con,
  "SET s3_region='auto';SET s3_endpoint='s3.valeria.science';"
)
Note

Note the use of the triple colon (:::) to access the internal function.

Now, we can read the data from the parquet file stored on the S3 bucket with the duckplyr_df_from_parquet() function. We can also specify the class of the output data frame with class = class(tibble()). In this case, I will use tibble.

flights <- duckplyr_df_from_parquet(
  "s3://public/flights.parquet",
  class = class(tibble())
)

flights
#> # A tibble: 336,776 Γ— 19
#>     year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#>    <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
#>  1  2013     1     1      517            515         2      830            819
#>  2  2013     1     1      533            529         4      850            830
#>  3  2013     1     1      542            540         2      923            850
#>  4  2013     1     1      544            545        -1     1004           1022
#>  5  2013     1     1      554            600        -6      812            837
#>  6  2013     1     1      554            558        -4      740            728
#>  7  2013     1     1      555            600        -5      913            854
#>  8  2013     1     1      557            600        -3      709            723
#>  9  2013     1     1      557            600        -3      838            846
#> 10  2013     1     1      558            600        -2      753            745
#> # β„Ή 336,766 more rows
#> # β„Ή 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
#> #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
#> #   hour <dbl>, minute <dbl>, time_hour <dttm>

From what I understand, all the data is pulled into the memory. This could be a problem if the data is too large. What we can do is to summarize the data to know how many rows are in the table.

duckplyr_df_from_parquet(
  "s3://public/flights.parquet",
  class = class(tibble())
) |>
  nrow()
#> [1] 336776

Or even have a glimpse() of the data.

duckplyr_df_from_parquet(
  "s3://public/flights.parquet",
  class = class(tibble())
) |>
  glimpse()
#> Rows: 336,776
#> Columns: 19
#> $ year           <int> 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2…
#> $ month          <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
#> $ day            <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
#> $ dep_time       <int> 517, 533, 542, 544, 554, 554, 555, 557, 557, 558, 558, …
#> $ sched_dep_time <int> 515, 529, 540, 545, 600, 558, 600, 600, 600, 600, 600, …
#> $ dep_delay      <dbl> 2, 4, 2, -1, -6, -4, -5, -3, -3, -2, -2, -2, -2, -2, -1…
#> $ arr_time       <int> 830, 850, 923, 1004, 812, 740, 913, 709, 838, 753, 849,…
#> $ sched_arr_time <int> 819, 830, 850, 1022, 837, 728, 854, 723, 846, 745, 851,…
#> $ arr_delay      <dbl> 11, 20, 33, -18, -25, 12, 19, -14, -8, 8, -2, -3, 7, -1…
#> $ carrier        <chr> "UA", "UA", "AA", "B6", "DL", "UA", "B6", "EV", "B6", "…
#> $ flight         <int> 1545, 1714, 1141, 725, 461, 1696, 507, 5708, 79, 301, 4…
#> $ tailnum        <chr> "N14228", "N24211", "N619AA", "N804JB", "N668DN", "N394…
#> $ origin         <chr> "EWR", "LGA", "JFK", "JFK", "LGA", "EWR", "EWR", "LGA",…
#> $ dest           <chr> "IAH", "IAH", "MIA", "BQN", "ATL", "ORD", "FLL", "IAD",…
#> $ air_time       <dbl> 227, 227, 160, 183, 116, 150, 158, 53, 140, 138, 149, 1…
#> $ distance       <dbl> 1400, 1416, 1089, 1576, 762, 719, 1065, 229, 944, 733, …
#> $ hour           <dbl> 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6…
#> $ minute         <dbl> 15, 29, 40, 45, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0…
#> $ time_hour      <dttm> 2013-01-01 10:00:00, 2013-01-01 10:00:00, 2013-01-01 1…

Now, let’s summarize the data by calculating the average departure delay by carrier.

flights |>
  summarise(mean_dep_delay = mean(dep_delay), .by = "carrier")
#> # A tibble: 16 Γ— 2
#>    carrier mean_dep_delay
#>    <chr>            <dbl>
#>  1 9E               16.7 
#>  2 F9               20.2 
#>  3 YV               19.0 
#>  4 AA                8.59
#>  5 DL                9.26
#>  6 B6               13.0 
#>  7 EV               20.0 
#>  8 WN               17.7 
#>  9 FL               18.7 
#> 10 AS                5.80
#> 11 UA               12.1 
#> 12 MQ               10.6 
#> 13 VX               12.9 
#> 14 HA                4.90
#> 15 US                3.78
#> 16 OO               12.6

duckplyr_df_from_parquet(
  "s3://public/flights.parquet",
  class = class(tibble())
) |>
  summarise(mean_dep_delay = mean(dep_delay), .by = "carrier")
#> # A tibble: 16 Γ— 2
#>    carrier mean_dep_delay
#>    <chr>            <dbl>
#>  1 9E               16.7 
#>  2 F9               20.2 
#>  3 YV               19.0 
#>  4 AA                8.59
#>  5 DL                9.26
#>  6 B6               13.0 
#>  7 EV               20.0 
#>  8 WN               17.7 
#>  9 FL               18.7 
#> 10 AS                5.80
#> 11 UA               12.1 
#> 12 MQ               10.6 
#> 13 VX               12.9 
#> 14 HA                4.90
#> 15 US                3.78
#> 16 OO               12.6

Scaling Up: Analyzing a larger dataset

Let’s try with a much larger dataset. I will use the NYC taxi data from 2019. The data is partitioned by month and stored in parquet partitioning. But before we can process, we need to change the endpoint.

DBI::dbSendQuery(
  con,
  "SET s3_region='auto';SET s3_endpoint='';"
)

duckplyr_df_from_file(
  "s3://duckplyr-demo-taxi-data/taxi-data-2019-partitioned/*/*.parquet",
  "read_parquet",
  options = list(hive_partitioning = TRUE),
  class = class(tibble())
) |>
  count()
#> # A tibble: 1 Γ— 1
#>          n
#>      <int>
#> 1 84393604

Impressive, isn’t it? With DuckDB, analyzing over 80 million rows of data is a so fast πŸ˜€.

Warning

Unless you have a lot of memory, do not run the code below (i.e. without the count() function). It will load the entire dataset in memory!

duckplyr_df_from_file(
  "s3://duckplyr-demo-taxi-data/taxi-data-2019-partitioned/*/*.parquet",
  "read_parquet",
  options = list(hive_partitioning = TRUE),
  class = class(tibble())
)

Performance Benchmarking

How long it took to count the rows? Let’s find out ⌚.

system.time({
  duckplyr_df_from_file(
    "s3://duckplyr-demo-taxi-data/taxi-data-2019-partitioned/*/*.parquet",
    "read_parquet",
    options = list(hive_partitioning = TRUE),
    class = class(tibble())
  ) |>
    count()
})
#>    user  system elapsed 
#>   0.016   0.004   2.304

It took less than 3 seconds to count the rows. This is impressive!

To wrap up, let’s do an actual analysis. We will calculate the median tip percentage by the number of passengers in the taxi.

duckplyr_df_from_file(
  "s3://duckplyr-demo-taxi-data/taxi-data-2019-partitioned/*/*.parquet",
  "read_parquet",
  options = list(hive_partitioning = TRUE),
  class = class(tibble())
) |>
  filter(total_amount > 0) |>
  filter(!is.na(passenger_count)) |>
  mutate(tip_pct = 100 * tip_amount / total_amount) |>
  summarise(
    avg_tip_pct = median(tip_pct),
    n = n(),
    .by = passenger_count
  ) |>
  arrange(desc(passenger_count))
#> # A tibble: 10 Γ— 3
#>    passenger_count avg_tip_pct        n
#>              <dbl>       <dbl>    <int>
#>  1               9        12.8      221
#>  2               8        12.4      274
#>  3               7        10.2      412
#>  4               6        16.6  2035161
#>  5               5        16.7  3391426
#>  6               4        12.8  1706047
#>  7               3        13.7  3575542
#>  8               2        14.5 12755829
#>  9               1        15.3 58967003
#> 10               0        13.7  1525284

Conclusion

By integrating DuckDB with dplyr via duckplyr, we unlock a powerful toolset for data analysis. Whether it’s exploring small datasets or crunching numbers in massive datasets, DuckDB’s efficiency and dplyr’s versatility make for a winning combination.

Bonus: comparing the performance with dbplyr

I recently stumbled across this discussion addressing the difference between duckplyr and dbplyr. Intrigued, I decided to compare the performance of duckplyr against dbplyr.

library(dplyr)
library(dbplyr)
library(bench)

f_dbplyr <- function() {
  con <- dbConnect(duckdb())

  dbSendQuery(con, "INSTALL httpfs; LOAD httpfs;")
  dbSendQuery(con, "SET s3_region='auto';SET s3_endpoint='';")

  df <- tbl(
    con,
    "read_parquet('s3://duckplyr-demo-taxi-data/taxi-data-2019-partitioned/*/*.parquet')"
  )

  df |>
    filter(total_amount > 0) |>
    filter(!is.na(passenger_count)) |>
    mutate(tip_pct = 100 * tip_amount / total_amount) |>
    summarise(
      avg_tip_pct = median(tip_pct),
      n = n(),
      .by = passenger_count
    ) |>
    arrange(desc(passenger_count))

  dbDisconnect(con)
}

f_duckplyr <- function() {
  con <- duckplyr:::get_default_duckdb_connection()

  dbSendQuery(con, "INSTALL httpfs; LOAD httpfs;")
  dbSendQuery(
    con,
    "SET s3_region='auto';SET s3_endpoint='';"
  )

  duckplyr_df_from_file(
    "s3://duckplyr-demo-taxi-data/taxi-data-2019-partitioned/*/*.parquet",
    "read_parquet",
    options = list(hive_partitioning = TRUE),
    class = class(tibble())
  ) |>
    filter(total_amount > 0) |>
    filter(!is.na(passenger_count)) |>
    mutate(tip_pct = 100 * tip_amount / total_amount) |>
    summarise(
      avg_tip_pct = median(tip_pct),
      n = n(),
      .by = passenger_count
    ) |>
    arrange(desc(passenger_count))
}

mark(f_dbplyr(), f_duckplyr(), check = FALSE)
#> # A tibble: 2 Γ— 6
#>   expression        min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>   <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 f_dbplyr()      1.25s    1.25s     0.803    5.31MB    0.803
#> 2 f_duckplyr()    6.93s    6.93s     0.144   51.34KB    0

The initial results show that using dbplyr is faster than duckplyr. This is interesting and I will need to investigate further to understand why.

Session info
#> ─ Session info ───────────────────────────────────────────────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.4.0 (2024-04-24)
#>  os       Linux Mint 21.3
#>  system   x86_64, linux-gnu
#>  ui       X11
#>  language en_CA:en
#>  collate  en_CA.UTF-8
#>  ctype    en_CA.UTF-8
#>  tz       America/Montreal
#>  date     2024-05-07
#>  pandoc   2.9.2.1 @ /usr/bin/ (via rmarkdown)
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────
#>  ! package     * version date (UTC) lib source
#>  P bench       * 1.1.3   2023-05-04 [?] RSPM
#>  P blob          1.2.4   2023-03-17 [?] RSPM
#>  P cachem        1.0.8   2023-05-01 [?] RSPM
#>  P cli           3.6.2   2023-12-11 [?] RSPM
#>  P collections   0.3.7   2023-01-05 [?] RSPM
#>  P DBI         * 1.2.2   2024-02-16 [?] RSPM
#>  P dbplyr      * 2.5.0   2024-03-19 [?] RSPM
#>  P devtools      2.4.5   2022-10-11 [?] RSPM (R 4.4.0)
#>  P digest        0.6.35  2024-03-11 [?] RSPM
#>  P dplyr       * 1.1.4   2023-11-17 [?] RSPM
#>  P duckdb      * 0.10.1  2024-04-02 [?] RSPM
#>  P duckplyr    * 0.3.2   2024-03-17 [?] RSPM
#>  P ellipsis      0.3.2   2021-04-29 [?] RSPM
#>  P evaluate      0.23    2023-11-01 [?] RSPM
#>  P fansi         1.0.6   2023-12-08 [?] RSPM
#>  P fastmap       1.1.1   2023-02-24 [?] RSPM
#>  P fs            1.6.4   2024-04-25 [?] CRAN (R 4.4.0)
#>  P generics      0.1.3   2022-07-05 [?] RSPM
#>  P glue          1.7.0   2024-01-09 [?] RSPM
#>  P htmltools     0.5.8.1 2024-04-04 [?] RSPM
#>  P htmlwidgets   1.6.4   2023-12-06 [?] RSPM
#>  P httpuv        1.6.15  2024-03-26 [?] RSPM
#>  P jsonlite      1.8.8   2023-12-04 [?] RSPM
#>  P knitr         1.46    2024-04-06 [?] RSPM
#>  P later         1.3.2   2023-12-06 [?] RSPM
#>  P lifecycle     1.0.4   2023-11-07 [?] RSPM
#>  P magrittr      2.0.3   2022-03-30 [?] RSPM
#>  P memoise       2.0.1   2021-11-26 [?] RSPM
#>  P mime          0.12    2021-09-28 [?] RSPM
#>  P miniUI        0.1.1.1 2018-05-18 [?] RSPM (R 4.4.0)
#>  R nvimcom     * 0.9.41  <NA>       [?] <NA>
#>  P pillar        1.9.0   2023-03-22 [?] RSPM
#>  P pkgbuild      1.4.4   2024-03-17 [?] RSPM (R 4.4.0)
#>  P pkgconfig     2.0.3   2019-09-22 [?] RSPM
#>  P pkgload       1.3.4   2024-01-16 [?] RSPM (R 4.4.0)
#>  P processx      3.8.4   2024-03-16 [?] RSPM
#>  P profmem       0.6.0   2020-12-13 [?] RSPM
#>  P profvis       0.3.8   2023-05-02 [?] RSPM (R 4.4.0)
#>  P promises      1.3.0   2024-04-05 [?] RSPM
#>  P ps            1.7.6   2024-01-18 [?] RSPM
#>  P purrr         1.0.2   2023-08-10 [?] RSPM
#>  P quarto      * 1.4     2024-03-06 [?] RSPM
#>  P R.cache       0.16.0  2022-07-21 [?] RSPM
#>  P R.methodsS3   1.8.2   2022-06-13 [?] RSPM
#>  P R.oo          1.26.0  2024-01-24 [?] RSPM
#>  P R.utils       2.12.3  2023-11-18 [?] RSPM
#>  P R6            2.5.1   2021-08-19 [?] RSPM
#>  P Rcpp          1.0.12  2024-01-09 [?] RSPM
#>  P remotes       2.5.0   2024-03-17 [?] RSPM (R 4.4.0)
#>  P renv          1.0.7   2024-04-11 [?] RSPM (R 4.4.0)
#>  P rlang         1.1.3   2024-01-10 [?] RSPM
#>  P rmarkdown     2.26    2024-03-05 [?] RSPM
#>  P rstudioapi    0.16.0  2024-03-24 [?] RSPM
#>  P sessioninfo   1.2.2   2021-12-06 [?] RSPM (R 4.4.0)
#>  P shiny         1.8.1.1 2024-04-02 [?] RSPM (R 4.4.0)
#>  P stringi       1.8.3   2023-12-11 [?] RSPM
#>  P stringr       1.5.1   2023-11-14 [?] RSPM
#>  P styler      * 1.10.3  2024-04-07 [?] RSPM
#>  P tibble        3.2.1   2023-03-20 [?] RSPM
#>  P tidyselect    1.2.1   2024-03-11 [?] RSPM
#>  P urlchecker    1.0.1   2021-11-30 [?] RSPM (R 4.4.0)
#>  P usethis       2.2.3   2024-02-19 [?] RSPM (R 4.4.0)
#>  P utf8          1.2.4   2023-10-22 [?] RSPM
#>  P vctrs         0.6.5   2023-12-01 [?] RSPM
#>  P withr         3.0.0   2024-01-16 [?] RSPM
#>  P xfun          0.43    2024-03-25 [?] RSPM
#>  P xtable        1.8-4   2019-04-21 [?] RSPM (R 4.4.0)
#>  P yaml          2.3.8   2023-12-11 [?] RSPM
#> 
#>  [1] /tmp/RtmpOkV4IM/renv-use-libpath-33b3525a9df88
#>  [2] /home/filoche/.cache/R/renv/sandbox/linux-linuxmint-jammy/R-4.4/x86_64-pc-linux-gnu/9a444a72
#> 
#>  P ── Loaded and on-disk path mismatch.
#>  R ── Package was removed from disk.
#> 
#> ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
renv.lock file
{
  "R": {
    "Version": "4.4.0",
    "Repositories": [
      {
        "Name": "RSPM",
        "URL": "https://packagemanager.posit.co/cran/latest"
      },
      {
        "Name": "CRAN",
        "URL": "https://cran.rstudio.com"
      }
    ]
  },
  "Packages": {
    "DBI": {
      "Package": "DBI",
      "Version": "1.2.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "methods"
      ],
      "Hash": "164809cd72e1d5160b4cb3aa57f510fe"
    },
    "R.cache": {
      "Package": "R.cache",
      "Version": "0.16.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R.methodsS3",
        "R.oo",
        "R.utils",
        "digest",
        "utils"
      ],
      "Hash": "fe539ca3f8efb7410c3ae2cf5fe6c0f8"
    },
    "R.methodsS3": {
      "Package": "R.methodsS3",
      "Version": "1.8.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "utils"
      ],
      "Hash": "278c286fd6e9e75d0c2e8f731ea445c8"
    },
    "R.oo": {
      "Package": "R.oo",
      "Version": "1.26.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R.methodsS3",
        "methods",
        "utils"
      ],
      "Hash": "4fed809e53ddb5407b3da3d0f572e591"
    },
    "R.utils": {
      "Package": "R.utils",
      "Version": "2.12.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R.methodsS3",
        "R.oo",
        "methods",
        "tools",
        "utils"
      ],
      "Hash": "3dc2829b790254bfba21e60965787651"
    },
    "R6": {
      "Package": "R6",
      "Version": "2.5.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "470851b6d5d0ac559e9d01bb352b4021"
    },
    "Rcpp": {
      "Package": "Rcpp",
      "Version": "1.0.12",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "methods",
        "utils"
      ],
      "Hash": "5ea2700d21e038ace58269ecdbeb9ec0"
    },
    "askpass": {
      "Package": "askpass",
      "Version": "1.2.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "sys"
      ],
      "Hash": "cad6cf7f1d5f6e906700b9d3e718c796"
    },
    "base64enc": {
      "Package": "base64enc",
      "Version": "0.1-3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "543776ae6848fde2f48ff3816d0628bc"
    },
    "bench": {
      "Package": "bench",
      "Version": "1.1.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "glue",
        "methods",
        "pillar",
        "profmem",
        "rlang",
        "stats",
        "tibble",
        "utils"
      ],
      "Hash": "d3920bdeb09b0dd8562c5ca24da562b7"
    },
    "blob": {
      "Package": "blob",
      "Version": "1.2.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "methods",
        "rlang",
        "vctrs"
      ],
      "Hash": "40415719b5a479b87949f3aa0aee737c"
    },
    "brew": {
      "Package": "brew",
      "Version": "1.0-10",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "8f4a384e19dccd8c65356dc096847b76"
    },
    "brio": {
      "Package": "brio",
      "Version": "1.1.5",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "c1ee497a6d999947c2c224ae46799b1a"
    },
    "bslib": {
      "Package": "bslib",
      "Version": "0.7.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "base64enc",
        "cachem",
        "fastmap",
        "grDevices",
        "htmltools",
        "jquerylib",
        "jsonlite",
        "lifecycle",
        "memoise",
        "mime",
        "rlang",
        "sass"
      ],
      "Hash": "8644cc53f43828f19133548195d7e59e"
    },
    "cachem": {
      "Package": "cachem",
      "Version": "1.0.8",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "fastmap",
        "rlang"
      ],
      "Hash": "c35768291560ce302c0a6589f92e837d"
    },
    "callr": {
      "Package": "callr",
      "Version": "3.7.6",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "processx",
        "utils"
      ],
      "Hash": "d7e13f49c19103ece9e58ad2d83a7354"
    },
    "cli": {
      "Package": "cli",
      "Version": "3.6.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "utils"
      ],
      "Hash": "1216ac65ac55ec0058a6f75d7ca0fd52"
    },
    "clipr": {
      "Package": "clipr",
      "Version": "0.8.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "utils"
      ],
      "Hash": "3f038e5ac7f41d4ac41ce658c85e3042"
    },
    "collections": {
      "Package": "collections",
      "Version": "0.3.7",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "90a0eda114ab0bef170ddbf5ef0cd93f"
    },
    "commonmark": {
      "Package": "commonmark",
      "Version": "1.9.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "5d8225445acb167abf7797de48b2ee3c"
    },
    "cpp11": {
      "Package": "cpp11",
      "Version": "0.4.7",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "5a295d7d963cc5035284dcdbaf334f4e"
    },
    "crayon": {
      "Package": "crayon",
      "Version": "1.5.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "grDevices",
        "methods",
        "utils"
      ],
      "Hash": "e8a1e41acf02548751f45c718d55aa6a"
    },
    "credentials": {
      "Package": "credentials",
      "Version": "2.0.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "askpass",
        "curl",
        "jsonlite",
        "openssl",
        "sys"
      ],
      "Hash": "c7844b32098dcbd1c59cbd8dddb4ecc6"
    },
    "curl": {
      "Package": "curl",
      "Version": "5.2.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "411ca2c03b1ce5f548345d2fc2685f7a"
    },
    "dbplyr": {
      "Package": "dbplyr",
      "Version": "2.5.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "DBI",
        "R",
        "R6",
        "blob",
        "cli",
        "dplyr",
        "glue",
        "lifecycle",
        "magrittr",
        "methods",
        "pillar",
        "purrr",
        "rlang",
        "tibble",
        "tidyr",
        "tidyselect",
        "utils",
        "vctrs",
        "withr"
      ],
      "Hash": "39b2e002522bfd258039ee4e889e0fd1"
    },
    "desc": {
      "Package": "desc",
      "Version": "1.4.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "cli",
        "utils"
      ],
      "Hash": "99b79fcbd6c4d1ce087f5c5c758b384f"
    },
    "devtools": {
      "Package": "devtools",
      "Version": "2.4.5",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "desc",
        "ellipsis",
        "fs",
        "lifecycle",
        "memoise",
        "miniUI",
        "pkgbuild",
        "pkgdown",
        "pkgload",
        "profvis",
        "rcmdcheck",
        "remotes",
        "rlang",
        "roxygen2",
        "rversions",
        "sessioninfo",
        "stats",
        "testthat",
        "tools",
        "urlchecker",
        "usethis",
        "utils",
        "withr"
      ],
      "Hash": "ea5bc8b4a6a01e4f12d98b58329930bb"
    },
    "diffobj": {
      "Package": "diffobj",
      "Version": "0.3.5",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "crayon",
        "methods",
        "stats",
        "tools",
        "utils"
      ],
      "Hash": "bcaa8b95f8d7d01a5dedfd959ce88ab8"
    },
    "digest": {
      "Package": "digest",
      "Version": "0.6.35",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "utils"
      ],
      "Hash": "698ece7ba5a4fa4559e3d537e7ec3d31"
    },
    "downlit": {
      "Package": "downlit",
      "Version": "0.4.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "brio",
        "desc",
        "digest",
        "evaluate",
        "fansi",
        "memoise",
        "rlang",
        "vctrs",
        "withr",
        "yaml"
      ],
      "Hash": "14fa1f248b60ed67e1f5418391a17b14"
    },
    "dplyr": {
      "Package": "dplyr",
      "Version": "1.1.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "cli",
        "generics",
        "glue",
        "lifecycle",
        "magrittr",
        "methods",
        "pillar",
        "rlang",
        "tibble",
        "tidyselect",
        "utils",
        "vctrs"
      ],
      "Hash": "fedd9d00c2944ff00a0e2696ccf048ec"
    },
    "duckdb": {
      "Package": "duckdb",
      "Version": "0.10.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "DBI",
        "R",
        "methods",
        "utils"
      ],
      "Hash": "af292ac7dd0245e3772fcc358a0db85a"
    },
    "duckplyr": {
      "Package": "duckplyr",
      "Version": "0.3.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "DBI",
        "R",
        "cli",
        "collections",
        "dplyr",
        "duckdb",
        "glue",
        "jsonlite",
        "lifecycle",
        "rlang",
        "tibble",
        "tidyselect",
        "utils",
        "vctrs"
      ],
      "Hash": "10a5bed777baa280ceb30b95c1feb293"
    },
    "ellipsis": {
      "Package": "ellipsis",
      "Version": "0.3.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "rlang"
      ],
      "Hash": "bb0eec2fe32e88d9e2836c2f73ea2077"
    },
    "evaluate": {
      "Package": "evaluate",
      "Version": "0.23",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "methods"
      ],
      "Hash": "daf4a1246be12c1fa8c7705a0935c1a0"
    },
    "fansi": {
      "Package": "fansi",
      "Version": "1.0.6",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "grDevices",
        "utils"
      ],
      "Hash": "962174cf2aeb5b9eea581522286a911f"
    },
    "fastmap": {
      "Package": "fastmap",
      "Version": "1.1.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "f7736a18de97dea803bde0a2daaafb27"
    },
    "fontawesome": {
      "Package": "fontawesome",
      "Version": "0.5.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "htmltools",
        "rlang"
      ],
      "Hash": "c2efdd5f0bcd1ea861c2d4e2a883a67d"
    },
    "fs": {
      "Package": "fs",
      "Version": "1.6.4",
      "Source": "Repository",
      "Repository": "CRAN",
      "Requirements": [
        "R",
        "methods"
      ],
      "Hash": "15aeb8c27f5ea5161f9f6a641fafd93a"
    },
    "generics": {
      "Package": "generics",
      "Version": "0.1.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "methods"
      ],
      "Hash": "15e9634c0fcd294799e9b2e929ed1b86"
    },
    "gert": {
      "Package": "gert",
      "Version": "2.0.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "askpass",
        "credentials",
        "openssl",
        "rstudioapi",
        "sys",
        "zip"
      ],
      "Hash": "f70d3fe2d9e7654213a946963d1591eb"
    },
    "gh": {
      "Package": "gh",
      "Version": "1.4.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "gitcreds",
        "glue",
        "httr2",
        "ini",
        "jsonlite",
        "lifecycle",
        "rlang"
      ],
      "Hash": "fbbbc48eba7a6626a08bb365e44b563b"
    },
    "gitcreds": {
      "Package": "gitcreds",
      "Version": "0.1.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "ab08ac61f3e1be454ae21911eb8bc2fe"
    },
    "glue": {
      "Package": "glue",
      "Version": "1.7.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "methods"
      ],
      "Hash": "e0b3a53876554bd45879e596cdb10a52"
    },
    "highr": {
      "Package": "highr",
      "Version": "0.10",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "xfun"
      ],
      "Hash": "06230136b2d2b9ba5805e1963fa6e890"
    },
    "htmltools": {
      "Package": "htmltools",
      "Version": "0.5.8.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "base64enc",
        "digest",
        "fastmap",
        "grDevices",
        "rlang",
        "utils"
      ],
      "Hash": "81d371a9cc60640e74e4ab6ac46dcedc"
    },
    "htmlwidgets": {
      "Package": "htmlwidgets",
      "Version": "1.6.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "grDevices",
        "htmltools",
        "jsonlite",
        "knitr",
        "rmarkdown",
        "yaml"
      ],
      "Hash": "04291cc45198225444a397606810ac37"
    },
    "httpuv": {
      "Package": "httpuv",
      "Version": "1.6.15",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "Rcpp",
        "later",
        "promises",
        "utils"
      ],
      "Hash": "d55aa087c47a63ead0f6fc10f8fa1ee0"
    },
    "httr": {
      "Package": "httr",
      "Version": "1.4.7",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "curl",
        "jsonlite",
        "mime",
        "openssl"
      ],
      "Hash": "ac107251d9d9fd72f0ca8049988f1d7f"
    },
    "httr2": {
      "Package": "httr2",
      "Version": "1.0.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "cli",
        "curl",
        "glue",
        "lifecycle",
        "magrittr",
        "openssl",
        "rappdirs",
        "rlang",
        "vctrs",
        "withr"
      ],
      "Hash": "03d741c92fda96d98c3a3f22494e3b4a"
    },
    "ini": {
      "Package": "ini",
      "Version": "0.3.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "6154ec2223172bce8162d4153cda21f7"
    },
    "jquerylib": {
      "Package": "jquerylib",
      "Version": "0.1.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "htmltools"
      ],
      "Hash": "5aab57a3bd297eee1c1d862735972182"
    },
    "jsonlite": {
      "Package": "jsonlite",
      "Version": "1.8.8",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "methods"
      ],
      "Hash": "e1b9c55281c5adc4dd113652d9e26768"
    },
    "knitr": {
      "Package": "knitr",
      "Version": "1.46",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "evaluate",
        "highr",
        "methods",
        "tools",
        "xfun",
        "yaml"
      ],
      "Hash": "6e008ab1d696a5283c79765fa7b56b47"
    },
    "later": {
      "Package": "later",
      "Version": "1.3.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "Rcpp",
        "rlang"
      ],
      "Hash": "a3e051d405326b8b0012377434c62b37"
    },
    "lifecycle": {
      "Package": "lifecycle",
      "Version": "1.0.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "glue",
        "rlang"
      ],
      "Hash": "b8552d117e1b808b09a832f589b79035"
    },
    "magrittr": {
      "Package": "magrittr",
      "Version": "2.0.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "7ce2733a9826b3aeb1775d56fd305472"
    },
    "memoise": {
      "Package": "memoise",
      "Version": "2.0.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "cachem",
        "rlang"
      ],
      "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c"
    },
    "mime": {
      "Package": "mime",
      "Version": "0.12",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "tools"
      ],
      "Hash": "18e9c28c1d3ca1560ce30658b22ce104"
    },
    "miniUI": {
      "Package": "miniUI",
      "Version": "0.1.1.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "htmltools",
        "shiny",
        "utils"
      ],
      "Hash": "fec5f52652d60615fdb3957b3d74324a"
    },
    "openssl": {
      "Package": "openssl",
      "Version": "2.1.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "askpass"
      ],
      "Hash": "ea2475b073243d9d338aa8f086ce973e"
    },
    "pillar": {
      "Package": "pillar",
      "Version": "1.9.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "cli",
        "fansi",
        "glue",
        "lifecycle",
        "rlang",
        "utf8",
        "utils",
        "vctrs"
      ],
      "Hash": "15da5a8412f317beeee6175fbc76f4bb"
    },
    "pkgbuild": {
      "Package": "pkgbuild",
      "Version": "1.4.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "callr",
        "cli",
        "desc",
        "processx"
      ],
      "Hash": "a29e8e134a460a01e0ca67a4763c595b"
    },
    "pkgconfig": {
      "Package": "pkgconfig",
      "Version": "2.0.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "utils"
      ],
      "Hash": "01f28d4278f15c76cddbea05899c5d6f"
    },
    "pkgdown": {
      "Package": "pkgdown",
      "Version": "2.0.9",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "bslib",
        "callr",
        "cli",
        "desc",
        "digest",
        "downlit",
        "fs",
        "httr",
        "jsonlite",
        "magrittr",
        "memoise",
        "purrr",
        "ragg",
        "rlang",
        "rmarkdown",
        "tibble",
        "whisker",
        "withr",
        "xml2",
        "yaml"
      ],
      "Hash": "8bf1151ed1a48328d71b937e651117a6"
    },
    "pkgload": {
      "Package": "pkgload",
      "Version": "1.3.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "crayon",
        "desc",
        "fs",
        "glue",
        "methods",
        "pkgbuild",
        "rlang",
        "rprojroot",
        "utils",
        "withr"
      ],
      "Hash": "876c618df5ae610be84356d5d7a5d124"
    },
    "praise": {
      "Package": "praise",
      "Version": "1.0.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "a555924add98c99d2f411e37e7d25e9f"
    },
    "prettyunits": {
      "Package": "prettyunits",
      "Version": "1.2.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "6b01fc98b1e86c4f705ce9dcfd2f57c7"
    },
    "processx": {
      "Package": "processx",
      "Version": "3.8.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "ps",
        "utils"
      ],
      "Hash": "0c90a7d71988856bad2a2a45dd871bb9"
    },
    "profmem": {
      "Package": "profmem",
      "Version": "0.6.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "utils"
      ],
      "Hash": "4974ce1d5ab22f266af90826f295f6c7"
    },
    "profvis": {
      "Package": "profvis",
      "Version": "0.3.8",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "htmlwidgets",
        "purrr",
        "rlang",
        "stringr",
        "vctrs"
      ],
      "Hash": "aa5a3864397ce6ae03458f98618395a1"
    },
    "promises": {
      "Package": "promises",
      "Version": "1.3.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R6",
        "Rcpp",
        "fastmap",
        "later",
        "magrittr",
        "rlang",
        "stats"
      ],
      "Hash": "434cd5388a3979e74be5c219bcd6e77d"
    },
    "ps": {
      "Package": "ps",
      "Version": "1.7.6",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "utils"
      ],
      "Hash": "dd2b9319ee0656c8acf45c7f40c59de7"
    },
    "purrr": {
      "Package": "purrr",
      "Version": "1.0.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "lifecycle",
        "magrittr",
        "rlang",
        "vctrs"
      ],
      "Hash": "1cba04a4e9414bdefc9dcaa99649a8dc"
    },
    "quarto": {
      "Package": "quarto",
      "Version": "1.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "jsonlite",
        "later",
        "processx",
        "rlang",
        "rmarkdown",
        "rstudioapi",
        "tools",
        "utils",
        "yaml"
      ],
      "Hash": "c94c271f9b998d116186a78b2a9b23c1"
    },
    "ragg": {
      "Package": "ragg",
      "Version": "1.3.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "systemfonts",
        "textshaping"
      ],
      "Hash": "082e1a198e3329d571f4448ef0ede4bc"
    },
    "rappdirs": {
      "Package": "rappdirs",
      "Version": "0.3.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "5e3c5dc0b071b21fa128676560dbe94d"
    },
    "rcmdcheck": {
      "Package": "rcmdcheck",
      "Version": "1.4.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R6",
        "callr",
        "cli",
        "curl",
        "desc",
        "digest",
        "pkgbuild",
        "prettyunits",
        "rprojroot",
        "sessioninfo",
        "utils",
        "withr",
        "xopen"
      ],
      "Hash": "8f25ebe2ec38b1f2aef3b0d2ef76f6c4"
    },
    "rematch2": {
      "Package": "rematch2",
      "Version": "2.1.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "tibble"
      ],
      "Hash": "76c9e04c712a05848ae7a23d2f170a40"
    },
    "remotes": {
      "Package": "remotes",
      "Version": "2.5.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "methods",
        "stats",
        "tools",
        "utils"
      ],
      "Hash": "3ee025083e66f18db6cf27b56e23e141"
    },
    "renv": {
      "Package": "renv",
      "Version": "1.0.7",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "utils"
      ],
      "Hash": "397b7b2a265bc5a7a06852524dabae20"
    },
    "rlang": {
      "Package": "rlang",
      "Version": "1.1.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "utils"
      ],
      "Hash": "42548638fae05fd9a9b5f3f437fbbbe2"
    },
    "rmarkdown": {
      "Package": "rmarkdown",
      "Version": "2.26",
      "Source": "Repository",
      "Repository": "CRAN",
      "Requirements": [
        "R",
        "bslib",
        "evaluate",
        "fontawesome",
        "htmltools",
        "jquerylib",
        "jsonlite",
        "knitr",
        "methods",
        "tinytex",
        "tools",
        "utils",
        "xfun",
        "yaml"
      ],
      "Hash": "9b148e7f95d33aac01f31282d49e4f44"
    },
    "roxygen2": {
      "Package": "roxygen2",
      "Version": "7.3.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "brew",
        "cli",
        "commonmark",
        "cpp11",
        "desc",
        "knitr",
        "methods",
        "pkgload",
        "purrr",
        "rlang",
        "stringi",
        "stringr",
        "utils",
        "withr",
        "xml2"
      ],
      "Hash": "c25fe7b2d8cba73d1b63c947bf7afdb9"
    },
    "rprojroot": {
      "Package": "rprojroot",
      "Version": "2.0.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "4c8415e0ec1e29f3f4f6fc108bef0144"
    },
    "rstudioapi": {
      "Package": "rstudioapi",
      "Version": "0.16.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "96710351d642b70e8f02ddeb237c46a7"
    },
    "rversions": {
      "Package": "rversions",
      "Version": "2.1.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "curl",
        "utils",
        "xml2"
      ],
      "Hash": "a9881dfed103e83f9de151dc17002cd1"
    },
    "sass": {
      "Package": "sass",
      "Version": "0.4.9",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R6",
        "fs",
        "htmltools",
        "rappdirs",
        "rlang"
      ],
      "Hash": "d53dbfddf695303ea4ad66f86e99b95d"
    },
    "sessioninfo": {
      "Package": "sessioninfo",
      "Version": "1.2.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "tools",
        "utils"
      ],
      "Hash": "3f9796a8d0a0e8c6eb49a4b029359d1f"
    },
    "shiny": {
      "Package": "shiny",
      "Version": "1.8.1.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "bslib",
        "cachem",
        "commonmark",
        "crayon",
        "fastmap",
        "fontawesome",
        "glue",
        "grDevices",
        "htmltools",
        "httpuv",
        "jsonlite",
        "later",
        "lifecycle",
        "methods",
        "mime",
        "promises",
        "rlang",
        "sourcetools",
        "tools",
        "utils",
        "withr",
        "xtable"
      ],
      "Hash": "54b26646816af9960a4c64d8ceec75d6"
    },
    "sourcetools": {
      "Package": "sourcetools",
      "Version": "0.1.7-1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "5f5a7629f956619d519205ec475fe647"
    },
    "stringi": {
      "Package": "stringi",
      "Version": "1.8.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "stats",
        "tools",
        "utils"
      ],
      "Hash": "058aebddea264f4c99401515182e656a"
    },
    "stringr": {
      "Package": "stringr",
      "Version": "1.5.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "glue",
        "lifecycle",
        "magrittr",
        "rlang",
        "stringi",
        "vctrs"
      ],
      "Hash": "960e2ae9e09656611e0b8214ad543207"
    },
    "styler": {
      "Package": "styler",
      "Version": "1.10.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R.cache",
        "cli",
        "magrittr",
        "purrr",
        "rlang",
        "rprojroot",
        "tools",
        "vctrs",
        "withr"
      ],
      "Hash": "93a2b1beac2437bdcc4724f8bf867e2c"
    },
    "sys": {
      "Package": "sys",
      "Version": "3.4.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "3a1be13d68d47a8cd0bfd74739ca1555"
    },
    "systemfonts": {
      "Package": "systemfonts",
      "Version": "1.0.6",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cpp11"
      ],
      "Hash": "6d538cff441f0f1f36db2209ac7495ac"
    },
    "testthat": {
      "Package": "testthat",
      "Version": "3.2.1.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "R6",
        "brio",
        "callr",
        "cli",
        "desc",
        "digest",
        "evaluate",
        "jsonlite",
        "lifecycle",
        "magrittr",
        "methods",
        "pkgload",
        "praise",
        "processx",
        "ps",
        "rlang",
        "utils",
        "waldo",
        "withr"
      ],
      "Hash": "3f6e7e5e2220856ff865e4834766bf2b"
    },
    "textshaping": {
      "Package": "textshaping",
      "Version": "0.3.7",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cpp11",
        "systemfonts"
      ],
      "Hash": "997aac9ad649e0ef3b97f96cddd5622b"
    },
    "tibble": {
      "Package": "tibble",
      "Version": "3.2.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "fansi",
        "lifecycle",
        "magrittr",
        "methods",
        "pillar",
        "pkgconfig",
        "rlang",
        "utils",
        "vctrs"
      ],
      "Hash": "a84e2cc86d07289b3b6f5069df7a004c"
    },
    "tidyr": {
      "Package": "tidyr",
      "Version": "1.3.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "cpp11",
        "dplyr",
        "glue",
        "lifecycle",
        "magrittr",
        "purrr",
        "rlang",
        "stringr",
        "tibble",
        "tidyselect",
        "utils",
        "vctrs"
      ],
      "Hash": "915fb7ce036c22a6a33b5a8adb712eb1"
    },
    "tidyselect": {
      "Package": "tidyselect",
      "Version": "1.2.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "glue",
        "lifecycle",
        "rlang",
        "vctrs",
        "withr"
      ],
      "Hash": "829f27b9c4919c16b593794a6344d6c0"
    },
    "tinytex": {
      "Package": "tinytex",
      "Version": "0.50",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "xfun"
      ],
      "Hash": "be7a76845222ad20adb761f462eed3ea"
    },
    "urlchecker": {
      "Package": "urlchecker",
      "Version": "1.0.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "curl",
        "tools",
        "xml2"
      ],
      "Hash": "409328b8e1253c8d729a7836fe7f7a16"
    },
    "usethis": {
      "Package": "usethis",
      "Version": "2.2.3",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "clipr",
        "crayon",
        "curl",
        "desc",
        "fs",
        "gert",
        "gh",
        "glue",
        "jsonlite",
        "lifecycle",
        "purrr",
        "rappdirs",
        "rlang",
        "rprojroot",
        "rstudioapi",
        "stats",
        "utils",
        "whisker",
        "withr",
        "yaml"
      ],
      "Hash": "d524fd42c517035027f866064417d7e6"
    },
    "utf8": {
      "Package": "utf8",
      "Version": "1.2.4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R"
      ],
      "Hash": "62b65c52671e6665f803ff02954446e9"
    },
    "vctrs": {
      "Package": "vctrs",
      "Version": "0.6.5",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "glue",
        "lifecycle",
        "rlang"
      ],
      "Hash": "c03fa420630029418f7e6da3667aac4a"
    },
    "waldo": {
      "Package": "waldo",
      "Version": "0.5.2",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "diffobj",
        "fansi",
        "glue",
        "methods",
        "rematch2",
        "rlang",
        "tibble"
      ],
      "Hash": "c7d3fd6d29ab077cbac8f0e2751449e6"
    },
    "whisker": {
      "Package": "whisker",
      "Version": "0.4.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "c6abfa47a46d281a7d5159d0a8891e88"
    },
    "withr": {
      "Package": "withr",
      "Version": "3.0.0",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "grDevices",
        "graphics"
      ],
      "Hash": "d31b6c62c10dcf11ec530ca6b0dd5d35"
    },
    "xfun": {
      "Package": "xfun",
      "Version": "0.43",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "grDevices",
        "stats",
        "tools"
      ],
      "Hash": "ab6371d8653ce5f2f9290f4ec7b42a8e"
    },
    "xml2": {
      "Package": "xml2",
      "Version": "1.3.6",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "cli",
        "methods",
        "rlang"
      ],
      "Hash": "1d0336142f4cd25d8d23cd3ba7a8fb61"
    },
    "xopen": {
      "Package": "xopen",
      "Version": "1.0.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "processx"
      ],
      "Hash": "423df1e86d5533fcb73c6b02b4923b49"
    },
    "xtable": {
      "Package": "xtable",
      "Version": "1.8-4",
      "Source": "Repository",
      "Repository": "RSPM",
      "Requirements": [
        "R",
        "stats",
        "utils"
      ],
      "Hash": "b8acdf8af494d9ec19ccb2481a9b11c2"
    },
    "yaml": {
      "Package": "yaml",
      "Version": "2.3.8",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "29240487a071f535f5e5d5a323b7afbd"
    },
    "zip": {
      "Package": "zip",
      "Version": "2.3.1",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "fcc4bd8e6da2d2011eb64a5e5cc685ab"
    }
  }
}

Citation

BibTeX citation:
@online{massicotte2024,
  author = {Massicotte, Philippe},
  title = {When Duckdb Meets Dplyr!},
  date = {2024-05-01},
  url = {https://www.pmassicotte.com/posts/2024-05-01-query-s3-duckplyr},
  langid = {en}
}
For attribution, please cite this work as:
Massicotte, Philippe. 2024. β€œWhen Duckdb Meets Dplyr!” May 1, 2024. https://www.pmassicotte.com/posts/2024-05-01-query-s3-duckplyr.