Skip to main content
This guide covers migration for SparkR, the R API for Apache Spark. For general SQL and DataFrame changes that also affect SparkR, review the SQL Migration Guide.
SparkR is deprecated as of Spark 4.0 and will be removed in a future version. Consider migrating to alternative solutions for R-based big data processing.

Upgrading from SparkR 3.5 to 4.0

SparkR Deprecation Notice

As of Spark 4.0, SparkR is officially deprecated. While it continues to work in Spark 4.0, you should plan to migrate away from SparkR.

Migration Alternatives

Consider these alternatives for R-based big data processing:

1. sparklyr Package

sparklyr provides a dplyr-compatible interface to Spark:
# Install sparklyr
install.packages("sparklyr")
library(sparklyr)

# Connect to Spark
sc <- spark_connect(master = "local")

# Use dplyr syntax
library(dplyr)

data <- spark_read_csv(sc, "data", "path/to/data.csv")

result <- data %>%
  filter(value > 100) %>%
  group_by(category) %>%
  summarize(
    avg_value = mean(value),
    count = n()
  ) %>%
  collect()

2. Arrow and DuckDB

For smaller-scale data processing:
library(arrow)
library(duckdb)

# Read data with Arrow
df <- read_parquet("data.parquet")

# Process with DuckDB for SQL operations
con <- dbConnect(duckdb::duckdb())
dbWriteTable(con, "data", df)

result <- dbGetQuery(con, "
  SELECT category, AVG(value) as avg_value, COUNT(*) as count
  FROM data
  WHERE value > 100
  GROUP BY category
")

Continuing to Use SparkR in Spark 4.0

If you must continue using SparkR in Spark 4.0:
library(SparkR)

# Initialize SparkSession
sparkR.session(master = "local[*]")

# Note: You may see deprecation warnings
df <- read.df("data.parquet", source = "parquet")
result <- SparkR::filter(df, df$value > 100)

Upgrading from SparkR 3.1 to 3.2

Automatic Installation Prompt

SparkR now prompts before downloading and installing the Spark distribution. Before (SparkR 3.1):
# Automatically downloaded Spark if not found
library(SparkR)
sparkR.session()  # Silent automatic download
After (SparkR 3.2):
# Prompts user for confirmation
library(SparkR)
sparkR.session()  # Asks: "Download Spark? (y/n)"

# Restore automatic behavior via environment variable
Sys.setenv(SPARKR_ASK_INSTALLATION = "FALSE")
library(SparkR)
sparkR.session()  # No prompt

Upgrading from SparkR 2.4 to 3.0

Deprecated Methods Removed

Several deprecated methods have been removed: Removed methods:
  • parquetFile() → Use read.parquet()
  • saveAsParquetFile() → Use write.parquet()
  • jsonFile() → Use read.json()
  • jsonRDD() → Use read.json()
Migration example:
# Before (SparkR 2.4)
df <- parquetFile("data.parquet")  # Deprecated
saveAsParquetFile(df, "output.parquet")  # Deprecated

# After (SparkR 3.0)
df <- read.parquet("data.parquet")
write.parquet(df, "output.parquet")

Upgrading from SparkR 2.3 to 2.4

Neural Network Layer Validation

The spark.mlp function now validates layer sizes. Before (SparkR 2.3):
# Invalid layer configuration silently accepted
model <- spark.mlp(
  data = df,
  label = "label",
  layers = c(1, 3)  # Only 3 output neurons for multiple labels
)
After (SparkR 2.4):
# Throws error for invalid configuration
model <- spark.mlp(
  data = df,
  label = "label",
  layers = c(10, 5, 2)  # Must match number of labels
)
# Error if output layer size doesn't match label count

Upgrading from SparkR 2.3.0 to 2.3.1

substr Function Fix

This is a breaking change that affects substring operations.
The substr function now correctly uses 1-based indexing, matching R’s behavior. Before (SparkR 2.3.0):
# Incorrectly used 0-based indexing
df <- createDataFrame(data.frame(text = "abcdef"))
result <- select(df, substr(df$text, 2, 4))
collect(result)
# Result: "abc" (positions 1-3, incorrectly)
After (SparkR 2.3.1+):
# Correctly uses 1-based indexing
df <- createDataFrame(data.frame(text = "abcdef"))
result <- select(df, substr(df$text, 2, 4))
collect(result)
# Result: "bcd" (positions 2-4, correctly)

Upgrading from SparkR 2.2 to 2.3

stringsAsFactors Parameter Fix

The stringsAsFactors parameter is now properly respected in collect().
# Before (SparkR 2.2): Parameter ignored
df <- createDataFrame(iris)
result <- collect(df, stringsAsFactors = TRUE)
# Result: Strings not converted to factors

# After (SparkR 2.3): Parameter works correctly
result <- collect(df, stringsAsFactors = TRUE)
# Result: Strings properly converted to factors

summary Function Output Change

The summary() function output has changed to provide more statistical options.
# SparkR 2.3: Can specify statistics to compute
summary(df, statistics = c("mean", "stddev", "min", "max"))

# Different from describe() output
describe(df)  # Basic statistics only

Version Mismatch Warning

SparkR now warns when package and JVM versions don’t match.
library(SparkR)
sparkR.session()
# Warning: SparkR package version 2.3.0 does not match Spark JVM 2.2.0

Upgrading from SparkR 2.1 to 2.2

numPartitions Parameter

New numPartitions parameter added to data frame creation functions.
# SparkR 2.2: Can control partitioning
df <- createDataFrame(
  data = iris,
  numPartitions = 4  # Explicitly set partition count
)

df2 <- as.DataFrame(
  data = iris,
  numPartitions = 8
)

createExternalTable Deprecation

createExternalTable() deprecated in favor of createTable(). Migration:
# Before (SparkR 2.1)
createExternalTable("table_name", path = "data", source = "parquet")

# After (SparkR 2.2)
createTable("table_name", path = "data", source = "parquet")

Derby Log Location

Derby log now saved to temporary directory.
# SparkR 2.2: Derby log location
sparkR.session(enableHiveSupport = TRUE)
# derby.log saved to tempdir()

LDA Optimizer Fix

The spark.lda function now correctly sets the optimizer.
# SparkR 2.2: Optimizer parameter now works correctly
model <- spark.lda(
  data = df,
  optimizer = "online",  # Now properly applied
  k = 10
)

Model Summary Matrix Format

Model summaries now return coefficients as matrices.
# SparkR 2.2: Coefficients as matrix
model <- spark.logit(label ~ features, data = df)
summary_obj <- summary(model)
coefs <- summary_obj$coefficients  # Now a matrix

# Apply to multiple functions:
# - spark.logit
# - spark.kmeans  
# - spark.glm
# - spark.gaussianMixture (added loglik)

Upgrading from SparkR 2.0 to 2.1

Cartesian Product Changes

join() no longer performs Cartesian products by default. Migration:
# Before (SparkR 2.0)
df1 <- createDataFrame(data.frame(a = 1:3))
df2 <- createDataFrame(data.frame(b = 1:3))
result <- join(df1, df2)  # Cartesian product

# After (SparkR 2.1)
result <- crossJoin(df1, df2)  # Explicit cross join

Upgrading from SparkR 1.6 to 2.0

Major API Changes

SparkR 2.0 introduced significant API changes:

DataFrame Renamed to SparkDataFrame

# Before (SparkR 1.6)
df <- createDataFrame(iris)
class(df)  # "DataFrame"

# After (SparkR 2.0)
df <- createDataFrame(iris)
class(df)  # "SparkDataFrame"

SparkSession Replaces SQLContext

# Before (SparkR 1.6)
sparkR.init()
sqlContext <- sparkRSQL.init(sc)

# After (SparkR 2.0)
spark <- sparkR.session()
# No separate SQLContext needed

Simplified Function Signatures

Many functions no longer require sqlContext parameter:
# Before (SparkR 1.6)
df <- read.json(sqlContext, "data.json")
tables(sqlContext)
cacheTable(sqlContext, "tableName")

# After (SparkR 2.0)
df <- read.json("data.json")
tables()  
cacheTable("tableName")

Temp Table Functions Renamed

# Before (SparkR 1.6)
registerTempTable(df, "temp")
dropTempTable("temp")

# After (SparkR 2.0)
createOrReplaceTempView(df, "temp")
dropTempView("temp")

Executor Environment Configuration

# Before (SparkR 1.6)
sparkR.init(sparkExecutorEnv = list(PATH = "/custom/path"))

# After (SparkR 2.0)
sparkR.session(
  sparkConfig = list(
    "spark.executorEnv.PATH" = "/custom/path"
  )
)

Best Practices for Migration

Testing Strategy

# Create test suite for migration
library(testthat)

test_that("DataFrame operations work correctly", {
  df <- createDataFrame(iris)
  result <- SparkR::filter(df, df$Sepal_Length > 5.0)
  expect_true(nrow(collect(result)) > 0)
})

test_that("Read/write operations function", {
  df <- createDataFrame(iris)
  write.parquet(df, "test_output.parquet")
  df2 <- read.parquet("test_output.parquet")
  expect_equal(nrow(collect(df)), nrow(collect(df2)))
})

Version Checking

# Check SparkR version
check_sparkr_version <- function(min_version) {
  current <- packageVersion("SparkR")
  if (current < min_version) {
    stop(paste(
      "SparkR version", min_version, "or higher required.",
      "Current version:", current
    ))
  }
}

check_sparkr_version("3.0.0")

Logging Configuration

# Enable verbose logging for debugging
sparkR.session(
  sparkConfig = list(
    "spark.sql.shuffle.partitions" = "4",
    "spark.logConf" = "true"
  )
)

Alternative: migrating to sparklyr

For new R projects, consider starting with sparklyr:
# Install sparklyr
install.packages("sparklyr")
library(sparklyr)

# Install Spark
spark_install(version = "3.5.0")

# Connect to Spark
sc <- spark_connect(master = "local")

# Use familiar dplyr syntax
library(dplyr)

df <- copy_to(sc, iris, "iris")

result <- df %>%
  filter(Sepal_Length > 5.0) %>%
  group_by(Species) %>%
  summarize(
    avg_sepal = mean(Sepal_Length),
    count = n()
  ) %>%
  collect()

print(result)

# Disconnect
spark_disconnect(sc)

Additional Resources

sparklyr

Recommended alternative for R users

SparkR Documentation

Official SparkR programming guide

See Also

Build docs developers (and LLMs) love