当前位置: 首页 > news >正文

Spark 中创建 DataFrame 的2种方式对比

spark.createDataFrame(data).toDF("name", "age")

spark.createDataFrame(spark.sparkContext.parallelize(data), schema)

创建df的方式有什么区别?

在 Spark 中,创建 DataFrame 的方式有多种,其中两种常见的方式是:

  1. spark.createDataFrame(data).toDF("name", "age")

  2. spark.createDataFrame(spark.sparkContext.parallelize(data), schema)

这两种方式的主要区别在于 数据来源 和 模式(Schema)的定义方式。下面详细分析它们的区别和适用场景。


1. spark.createDataFrame(data).toDF("name", "age")

特点
  • 数据来源data 是一个本地集合(如 Seq 或 List),Spark 会将其并行化为分布式数据集(RDD)。

  • 模式推断:Spark 会自动推断数据的模式(Schema),并根据列的顺序为列命名。

  • 列名指定:通过 toDF("name", "age") 显式指定列名。

示例
import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder()
  .appName("DataFrame Example")
  .master("local[*]")
  .getOrCreate()

// 数据是一个本地集合
val data = Seq(("Alice", 25), ("Bob", 30), ("Charlie", 35))

// 创建 DataFrame,并指定列名
val df = spark.createDataFrame(data).toDF("name", "age")

df.show()

输出:

+-------+---+
|   name|age|
+-------+---+
|  Alice| 25|
|    Bob| 30|
|Charlie| 35|
+-------+---+
适用场景
  • 数据量较小,可以直接在本地集合中定义。

  • 不需要显式定义复杂的模式(Schema)。

  • 列名可以通过 toDF 简单指定。


2. spark.createDataFrame(spark.sparkContext.parallelize(data), schema)

特点
  • 数据来源data 是一个本地集合,通过 spark.sparkContext.parallelize(data) 将其显式转换为 RDD。

  • 模式定义:需要显式定义一个模式(StructType),指定每列的名称和数据类型。

  • 灵活性:适合处理复杂的数据结构(如嵌套结构体)。

示例
import org.apache.spark.sql.{SparkSession, Row}
import org.apache.spark.sql.types._

val spark = SparkSession.builder()
  .appName("DataFrame Example")
  .master("local[*]")
  .getOrCreate()

// 数据是一个本地集合,每个元素是一个 Row 对象
val data = Seq(
  Row("Alice", 25),
  Row("Bob", 30),
  Row("Charlie", 35)
)

// 定义模式
val schema = new StructType()
  .add(StructField("name", StringType, nullable = false))
  .add(StructField("age", IntegerType, nullable = false))

// 创建 DataFrame
val df = spark.createDataFrame(spark.sparkContext.parallelize(data), schema)

df.show()

输出:

+-------+---+
|   name|age|
+-------+---+
|  Alice| 25|
|    Bob| 30|
|Charlie| 35|
+-------+---+
适用场景
  • 数据量较大,需要显式并行化为 RDD。

  • 数据结构复杂,需要显式定义模式(Schema)。

  • 需要更精确地控制列的数据类型和是否允许为空。


3. 主要区别

特性spark.createDataFrame(data).toDF("name", "age")spark.createDataFrame(spark.sparkContext.parallelize(data), schema)
数据来源本地集合(自动并行化为 RDD)本地集合(显式并行化为 RDD)
模式定义自动推断模式需要显式定义模式(StructType
列名指定通过 toDF 指定列名在模式中定义列名
数据类型控制自动推断数据类型可以显式指定每列的数据类型
是否允许为空默认允许为空可以显式指定是否允许为空
适用场景简单数据结构,数据量较小复杂数据结构,数据量较大

4. 选择哪种方式?

  • 使用 spark.createDataFrame(data).toDF("name", "age") 的情况

    • 数据量较小,可以直接在本地集合中定义。

    • 数据结构简单,不需要显式定义模式。

    • 列名可以通过 toDF 简单指定。

  • 使用 spark.createDataFrame(spark.sparkContext.parallelize(data), schema) 的情况

    • 数据量较大,需要显式并行化为 RDD。

    • 数据结构复杂,需要显式定义模式。

    • 需要精确控制列的数据类型和是否允许为空。


5. 复杂数据结构示例

如果需要处理嵌套结构体(如数组或结构体),推荐使用显式定义模式的方式。

示例:嵌套结构体
import org.apache.spark.sql.{SparkSession, Row}
import org.apache.spark.sql.types._

val spark = SparkSession.builder()
  .appName("Nested DataFrame Example")
  .master("local[*]")
  .getOrCreate()

// 数据是一个本地集合,包含嵌套结构
val data = Seq(
  Row("Alice", Row("Java", 5)),
  Row("Bob", Row("Python", 4))
)

// 定义模式
val schema = new StructType()
  .add(StructField("name", StringType, nullable = false))
  .add(StructField("skill", new StructType()
    .add(StructField("name", StringType, nullable = false))
    .add(StructField("level", IntegerType, nullable = false))
  ))

// 创建 DataFrame
val df = spark.createDataFrame(spark.sparkContext.parallelize(data), schema)

df.printSchema()
df.show()

输出:

root
 |-- name: string (nullable = false)
 |-- skill: struct (nullable = false)
 |    |-- name: string (nullable = false)
 |    |-- level: integer (nullable = false)

+-----+----------+
| name|     skill|
+-----+----------+
|Alice| [Java, 5]|
|  Bob|[Python, 4]|
+-----+----------+

总结

  • spark.createDataFrame(data).toDF("name", "age"):适合简单场景,自动推断模式。

  • spark.createDataFrame(spark.sparkContext.parallelize(data), schema):适合复杂场景,显式定义模式。

根据数据结构和需求选择合适的方式即可!如果还有其他问题,欢迎继续提问。

相关文章:

  • 【统计学相关笔记】抽样基本定理的证明
  • Linux与深入HTTP序列化和反序列化
  • 【LeetCode】622、设计循环队列
  • LuaJIT 学习(4)—— FFI 语义
  • JavaScript进阶篇:二、 对象与面向对象编程
  • 组合Ⅲ 力扣216
  • 卫语句优化多层if else嵌套
  • Typora最新版破解教程
  • 最新版VMware 17.6.3安装包分享
  • 功耗电流和耗电量的获取
  • 大数据 spark hive 总结
  • react(一):特点-基本使用-JSX语法
  • 【大模型(LLMs)RAG 检索增强生成 面经】
  • 【HTML】二、列表、表格
  • 【JAVA】七、基础知识“if+switch+循环结构”详细讲解~简单易懂!
  • Trae:与AI结伴,开启编程新体验
  • springboot438-基于SpringBoot的数字化教学资源管理系统(源码+数据库+纯前后端分离+部署讲解等)
  • 王者荣耀道具页面爬虫(json格式数据)
  • 线程、多线程以及线程池的关系与用法
  • Xinference大模型配置介绍并通过git-lfs、hf-mirror安装
  • 结婚这件事,年轻人到底怎么想的?
  • 俄宣布停火三天,外交部:希望各方继续通过对话谈判解决危机
  • “麒麟王”亮相上海彩市,体彩即开票“瑞兽家族”迎来新成员
  • 言短意长|新能源领军者密集捐赠母校
  • 新华每日电讯:从上海街区经济看账面、市面、人面、基本面
  • 日中友好议员联盟代表团访问中国人民对外友好协会