Run 'dplyr' verbs on 'Dask' data frames from R. Connect to a local 'Dask' client or a remote scheduler, copy R data frames onto the cluster, read and write Parquet and CSV, and collect results as 'tibble' objects. Computation stays in Python workers through 'reticulate'; R only builds the graph. A Python installation with the 'dask' package is required.
R front-end for Dask, aimed at the same user-facing
shape as sparklyr (connect / copy_to / dplyr /
read-write / collect). R talks to the Python Dask client through
reticulate. Workers stay Python.
install.packages("dasklyr")
Until the package is on CRAN, install from this repository (Rscript on
PATH):
install.packages(".", repos = NULL, type = "source")
Install Python Dask at the same major release as the cluster you connect to:
pip install "dask[dataframe,distributed]" pyarrow pandas
Point reticulate at that interpreter with environment variables, not hardcoded paths:
| Variable | Purpose |
|---|---|
DASKLYR_PYTHON |
Python executable with dask (read by this package) |
RETICULATE_PYTHON |
Same, via reticulate |
DASK_SCHEDULER |
Cluster address, for example tcp:// host port 8786 |
Connect to a local client or a remote scheduler. dask_connect() with no
arguments is always local; pass master for a cluster (or
dask_connect(Sys.getenv("DASK_SCHEDULER"))).
library(dasklyr)
sc <- dask_connect(master = "local")
# sc <- dask_connect(master = Sys.getenv("DASK_SCHEDULER"))
The returned connection (sc) is a dplyr source. The same master +
app_name pair reuses an open connection.
Copy data frames from R into Dask, then use dplyr verbs. Computation stays
lazy until collect().
library(dplyr)
students <- data.frame(
name = c("Ann", "Bob", "Cara", "Dan"),
class = c("a", "a", "b", "b"),
math = c(92L, 78L, 88L, 95L),
english = c(85L, 90L, 76L, 88L)
)
classes <- data.frame(
class = c("a", "b"),
teacher = c("Chen", "Liu")
)
st <- copy_to(sc, students, overwrite = TRUE)
cl <- copy_to(sc, classes, overwrite = TRUE)
src_tbls(sc)
Filter, mutate, aggregate:
st %>%
filter(math >= 90) %>%
mutate(total = math + english) %>%
group_by(class) %>%
summarise(n = n(), avg_math = mean(math), .groups = "drop") %>%
collect()
Joins use the same by argument as dplyr, including named c("a" = "b"):
st %>%
left_join(cl, by = "class") %>%
select(name, class, teacher, math) %>%
collect()
Supported verbs: select, rename, filter (comparisons, %in%, is.na),
mutate (columns, literals, + - * /), arrange / desc(), group_by /
ungroup, summarise (n(), n_distinct, mean / sum / min / max),
count, distinct, slice_head, left_join / inner_join / semi_join,
collect().
head() is the first rows of the first partition. Use slice_head()
when you need a global first-n.
Window functions, across(), and nested case_when are not implemented.
Rscript examples/local_demo.R
dask_write_parquet(st, "students.parquet", overwrite = TRUE)
pq <- dask_read_parquet(sc, "students_pq", "students.parquet")
dask_write_csv(st, "students.csv")
csv <- dask_read_csv(sc, "students_csv", "students.csv")
path must be visible to workers. A laptop tempfile() is fine for
master = "local". On a Docker cluster it is not your Windows temp
directory; use a shared volume or object store.
Counterparts of sparklyr's sdf_* helpers, named ddf_*:
ddf_npartitions(st)
ddf_schema(st)
ddf_nrow(st)
ddf_repartition(st, npartitions = 4)
ddf_persist(st)
dask_dataframe(st) returns the Python Dask DataFrame.
dask_invoke(st, "repartition", npartitions = 2L) calls an unwrapped
Python method (sparklyr's invoke()).
dask_web(sc) # dashboard URL (opens a browser when interactive)
dask_connection_find()
dask_disconnect(sc)
dask_disconnect_all()
Image tag is pinned to dask 2026.8.0. Scheduler port 8786, dashboard
port 8787 on the scheduler host (Docker publishes these on the local
machine).
The official image is a conda stack (often Python 3.10 / pandas 2.x). Your
client Python should use the same dask release; other libraries may
still warn VersionMismatchWarning. Computations can still run. For fewer
warnings, match Python/pandas as well, or install lz4 on the client.
docker compose up -d --wait --scale worker=2
Rscript examples/cluster_demo.R
docker compose down
Or examples/run_cluster_demo.ps1 (docker and Rscript on PATH).
Default scheduler: set DASK_SCHEDULER to the scheduler tcp:// address
(Docker Compose uses host port 8786).
MLlib-style ml_*, running R on workers (spark_apply), Spark streaming,
JDBC, and a SQL dbGetQuery surface. Those have no Dask counterpart worth
shipping as empty wrappers.