Bootstrap

Spark中Dataset方法详解

一、数据清洗核心方法

1. 处理缺失值
方法说明示例代码
na().drop()删除包含空值的行Dataset<Row> cleaned = dataset.na().drop();
na().fill(value)用指定值填充所有空值Dataset<Row> filled = dataset.na().fill(0);
na().fill(Map<String,Object>)按列填充不同值Map<String,Object> fills = new HashMap<>(); fills.put("age", 0); dataset.na().fill(fills);
2. 去重处理
方法说明示例代码
dropDuplicates()删除完全重复的行Dataset<Row> unique = dataset.dropDuplicates();
dropDuplicates(colNames)根据指定列去重Dataset<Row> unique = dataset.dropDuplicates(new String[]{"id"});
3. 过滤无效数据
方法说明示例代码
filter(condition)根据条件过滤行Dataset<Row> valid = dataset.filter(col("age").gt(0));
where(condition)filterDataset<Row> valid = dataset.where("salary > 1000");
4. 类型转换
方法说明示例代码
withColumn(colName, expr)转换列类型或计算新列Dataset<Row> converted = dataset.withColumn("age", col("age").cast("int"));
cast(DataType)强制类型转换col("timestamp").cast(DataTypes.TimestampType)
5. 列操作
方法说明示例代码
select(cols)选择特定列Dataset<Row> selected = dataset.select(col("name"), col("age"));
withColumnRenamed(old, new)重命名列Dataset<Row> renamed = dataset.withColumnRenamed("oldName", "newName");
drop(colName)删除列Dataset<Row> reduced = dataset.drop("unusedColumn");
6. 字符串处理
方法说明示例代码
regexp_replace()正则替换functions.regexp_replace(col("email"), "@.*", "")
trim()去除首尾空格col("name").trim()
substr(start, length)截取子字符串col("phone").substr(0, 3)

二、Dataset 核心操作方法

1. 数据加载与保存
方法说明示例代码
read().csv(path)读取 CSV 文件Dataset<Row> df = spark.read().csv("hdfs:///input.csv");
write().parquet(path)保存为 Parquet 格式df.write().parquet("hdfs:///output.parquet");
write().jdbc(...)写入关系型数据库.option("url", "jdbc:mysql://...") .option("dbtable", "table")
2. 聚合操作
方法说明示例代码
groupBy(cols)按列分组GroupedData grouped = df.groupBy("department");
agg(exprs)聚合计算grouped.agg(avg("salary"), max("age"));
3. 数据转换
方法说明示例代码
join(otherDataset, condition)表连接df1.join(df2, df1.col("id").equalTo(df2.col("id")));
union(otherDataset)合并数据集Dataset<Row> combined = df1.union(df2);
4. 数据探查
方法说明示例代码
show()打印前 N 行数据df.show(10);
printSchema()打印 Schemadf.printSchema();
describe(cols)统计数值列的基本信息df.describe("age", "salary").show();

三、完整数据清洗示例

import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;
import static org.apache.spark.sql.functions.*;
​
public class DataCleaningExample {
    public static void main(String[] args) {
        SparkSession spark = SparkSession.builder()
                .appName("Data Cleaning Demo")
                .master("local[*]")
                .getOrCreate();
​
        // 1. 读取原始数据
        Dataset<Row> rawData = spark.read()
                .option("header", true)
                .option("inferSchema", true)
                .csv("hdfs:///input.csv");
​
        // 2. 数据清洗流程
        Dataset<Row> cleanedData = rawData
                // 处理空值: 删除全空行
                .na().drop("all")
                // 填充特定列空值
                .na().fill(0, new String[]{"age"})
                // 过滤无效年龄
                .filter(col("age").geq(0).and(col("age").leq(100)))
                // 类型转换
                .withColumn("birth_year", 
                    functions.lit(2023).minus(col("age")).cast("int"))
                // 字符串处理
                .withColumn("name", trim(col("name")))
                // 去重
                .dropDuplicates(new String[]{"id"})
                // 选择最终列
                .select("id", "name", "age", "birth_year");
​
        // 3. 保存清洗结果
        cleanedData.write()
                .mode("overwrite")
                .parquet("hdfs:///cleaned_data");
​
        spark.stop();
    }
}

四、性能优化技巧

  1. 分区策略

    // 调整读取分区数
    spark.read().option("basePath", "/data")
        .csv("hdfs:///input_*.csv")
        .repartition(200);
    ​
    // 按列分区保存
    cleanedData.write()
        .partitionBy("year", "month")
        .parquet("hdfs:///partitioned_data");

  2. 缓存机制

    Dataset<Row> cachedDF = df.cache(); // MEMORY_AND_DISK

  3. 广播变量

    List<String> validCountries = Arrays.asList("US", "CN", "EU");
    Broadcast<List<String>> broadcastVar = spark.sparkContext().broadcast(validCountries);
    df.filter(col("country").isin(broadcastVar.value()));

  4. 并行度控制

    park.conf().set("spark.sql.shuffle.partitions", "200");


五、常见问题处理

问题解决方案
内存不足 (OOM)增加 Executor 内存:spark.executor.memory=8g
数据倾斜使用 repartitionsalt 技术分散热点数据
类型转换失败使用 try_cast 或先过滤无效数据
字符串编码问题指定编码格式:.option("encoding", "UTF-8")

;