在 Spark 中,创建 DataFrame 和 Dataset 的多种方式

在 Spark 中,创建 DataFrame 和 Dataset 有多种方式,以下是最常用的方法(示例以 Scala/Python 为主):

一、创建 DataFrame

1. 从结构化文件创建(最常用)
# Python (PySpark)
# JSON 文件
df_json = spark.read.json("path/to/file.json")

# CSV 文件(带选项)
df_csv = (spark.read
          .option("header", "true")
          .option("inferSchema", "true")
          .csv("path/to/file.csv"))

# Parquet 文件
df_parquet = spark.read.parquet("path/to/file.parquet")
// Scala
// JSON
val dfJson = spark.read.json("path/to/file.json")

// CSV(带选项)
val dfCsv = spark.read
  .option("header", "true")
  .option("inferSchema", "true")
  .csv("path/to/file.csv")

// Parquet
val dfParquet = spark.read.parquet("path/to/file.parquet")
2. 从 RDD 创建
# Python
from pyspark.sql import Row

# 创建 RDD
rdd = sc.parallelize([("Alice", 34), ("Bob", 45)])

# 方法1:指定列名
df1 = rdd.toDF(["name", "age"])

# 方法2:使用 Row 对象
rows = rdd.map(lambda x: Row(name=x[0], age=x[1]))
df2 = spark.createDataFrame(rows)
// Scala
import spark.implicits._

// 创建 RDD
val rdd = sc.parallelize(Seq(("Alice", 34), ("Bob", 45)))

// 方法1:直接转 DataFrame(指定列名)
val df1 = rdd.toDF("name", "age")

// 方法2:通过 case class
case class Person(name: String, age: Int)
val df2 = rdd.map(p => Person(p._1, p._2)).toDF()
3. 从 Pandas DataFrame 创建(仅 PySpark)
import pandas as pd
pandas_df = pd.DataFrame({"id": [1, 2], "value": ["A", "B"]})
spark_df = spark.createDataFrame(pandas_df)
4. 从 Hive 表创建
# Python
df_hive = spark.sql("SELECT * FROM my_hive_table")
# 或
df_hive = spark.table("my_hive_table")
// Scala
val dfHive = spark.sql("SELECT * FROM my_hive_table")
// 或
val dfHive = spark.table("my_hive_table")
5. 从 JDBC 数据库创建
# Python
jdbc_df = (spark.read
  .format("jdbc")
  .option("url", "jdbc:postgresql:dbserver")
  .option("dbtable", "schema.tablename")
  .option("user", "username")
  .option("password", "password")
  .load())
6. 编程方式创建(测试用)
# Python
from pyspark.sql.types import *

schema = StructType([
  StructField("id", IntegerType(), True),
  StructField("name", StringType(), True)
])

data = [(1, "Alice"), (2, "Bob")]
df = spark.createDataFrame(data, schema)

二、创建 Dataset(仅 Scala/Java)

1. 从集合创建
case class Person(name: String, age: Int)

// 方法1:使用 createDataset
val ds1 = spark.createDataset(Seq(
  Person("Alice", 34), 
  Person("Bob", 45)
))

// 方法2:隐式转换
import spark.implicits._
val ds2 = Seq(Person("Alice", 34), Person("Bob", 45)).toDS()
2. 从 DataFrame 转换(添加类型信息)
val df = spark.read.json("people.json") // DataFrame = Dataset[Row]
val ds = df.as[Person] // 转换为 Dataset[Person]
3. 从 RDD 创建
val rdd = sc.parallelize(Seq(Person("Alice", 34), Person("Bob", 45)))
val ds = spark.createDataset(rdd)

三、关键注意事项

  1. Schema 处理:

    • 文件读取时使用 inferSchema=true 自动推断(可能不准确)
    • 显式定义 Schema 可提高性能和准确性
    from pyspark.sql.types import *
    schema = StructType([
      StructField("name", StringType()),
      StructField("age", IntegerType())
    ])
    df = spark.read.schema(schema).json("data.json")
    
  2. 性能优化:

    • Parquet/ORC 格式比 JSON/CSV 性能更好
    • 批量数据优先使用 spark.read 而非 createDataFrame
  3. 类型安全:

    • Dataset 仅在 JVM 语言(Scala/Java)中支持类型安全
    • PySpark/R 的 DataFrame 本质是 Dataset[Row]
  4. 数据源选项:

    # 示例:读取 CSV 的更多选项
    df = (spark.read
          .option("delimiter", ";")
          .option("quote", "'")
          .option("escape", "\\")
          .option("nullValue", "NA")
          .csv("file.csv"))
    

四、创建方式对比

数据源DataFrame 支持Dataset 支持适用场景
JSON/CSV/Parquet 文件✓ (转换后)大数据文件导入
RDD从现有 RDD 转换
Hive 表✓ (转换后)数据仓库集成
JDBC 数据库关系型数据库查询
Pandas DataFrame✓ (PySpark)与 Python 生态集成
内存集合测试和小数据

五、最佳实践

  1. 生产环境:

    • 优先使用 Parquet/ORC 文件格式
    • 显式定义 Schema 避免推断开销
    • 批量数据使用 spark.read 直接读取
  2. 开发测试:

    • 小数据集用 spark.createDataFrame()
    • 使用 case class 创建类型安全的 Dataset(Scala)
  3. 类型转换:

    // Scala 示例:DataFrame → Dataset
    val ds: Dataset[Person] = df.as[Person]
    
    // Dataset → DataFrame
    val df: DataFrame = ds.toDF()
    
  4. 错误处理:

    • 文件不存在时使用 spark.read.option("pathGlobFilter", "*.parquet")
    • 模式不匹配时使用 .option("mode", "DROPMALFORMED")

通过灵活组合这些方法,可以在 Spark 中高效地创建和转换结构化数据集,充分利用 DataFrame/Dataset API 的性能优势和易用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值