MySQL(149)如何进行数据清洗?

数据清洗在数据处理和分析过程中至关重要,确保数据质量和一致性。以下是一个详细的指南,展示如何使用Java进行数据清洗,包括处理缺失值、重复值、异常值、数据类型转换以及标准化等步骤。

一、准备工作

确保安装有Java开发环境(JDK)和Maven或Gradle等依赖管理工具。我们将使用Apache Commons CSV库来处理CSV文件,并使用Java标准库进行数据清洗操作。

二、加载数据

首先,我们加载数据。假设我们有一个CSV文件(data.csv)作为数据源。

1. 添加依赖

在Maven项目的pom.xml文件中添加Apache Commons CSV库的依赖:

xml 复制代码
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv</artifactId>
    <version>1.8</version>
</dependency>

2. 加载CSV文件

java 复制代码
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.List;

public class DataLoader {

    public static List<CSVRecord> loadData(String filePath) throws IOException {
        CSVParser parser = CSVParser.parse(Paths.get(filePath), CSVFormat.DEFAULT.withFirstRecordAsHeader());
        return parser.getRecords();
    }

    public static void main(String[] args) {
        try {
            List<CSVRecord> records = loadData("data.csv");
            System.out.println("Data loaded successfully.");
            System.out.println(records.get(0));
        } catch (IOException e) {
            System.err.println("Failed to load data: " + e.getMessage());
        }
    }
}

三、处理缺失值

1. 检查缺失值

java 复制代码
public static void checkMissingValues(List<CSVRecord> records) {
    for (CSVRecord record : records) {
        for (String field : record) {
            if (field == null || field.trim().isEmpty()) {
                System.out.println("Missing value found in record: " + record);
            }
        }
    }
}

2. 填充缺失值

假设需要使用均值填充缺失值,对于数值类型的列。

java 复制代码
import java.util.HashMap;
import java.util.Map;

public class MissingValueHandler {

    public static List<CSVRecord> fillMissingValuesWithMean(List<CSVRecord> records, String columnName) {
        double sum = 0;
        int count = 0;
        Map<CSVRecord, Double> missingRecords = new HashMap<>();

        for (CSVRecord record : records) {
            String value = record.get(columnName);
            if (value == null || value.trim().isEmpty()) {
                missingRecords.put(record, null);
            } else {
                double numericValue = Double.parseDouble(value);
                sum += numericValue;
                count++;
            }
        }

        double mean = sum / count;
        for (CSVRecord record : missingRecords.keySet()) {
            record.toMap().put(columnName, String.valueOf(mean));
        }

        return records;
    }
}

四、处理重复值

1. 检查重复值

java 复制代码
import java.util.HashSet;
import java.util.Set;

public class DuplicateHandler {

    public static void checkDuplicates(List<CSVRecord> records) {
        Set<CSVRecord> uniqueRecords = new HashSet<>();
        for (CSVRecord record : records) {
            if (!uniqueRecords.add(record)) {
                System.out.println("Duplicate record found: " + record);
            }
        }
    }
}

2. 删除重复值

java 复制代码
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

public class DuplicateHandler {

    public static List<CSVRecord> removeDuplicates(List<CSVRecord> records) {
        Set<CSVRecord> uniqueRecords = new LinkedHashSet<>(records);
        return new ArrayList<>(uniqueRecords);
    }
}

五、处理异常值

1. 使用统计方法检测异常值

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class OutlierHandler {

    public static List<CSVRecord> removeOutliers(List<CSVRecord> records, String columnName) {
        List<Double> values = new ArrayList<>();
        for (CSVRecord record : records) {
            values.add(Double.parseDouble(record.get(columnName)));
        }

        double q1 = getPercentile(values, 25);
        double q3 = getPercentile(values, 75);
        double iqr = q3 - q1;

        double lowerBound = q1 - 1.5 * iqr;
        double upperBound = q3 + 1.5 * iqr;

        List<CSVRecord> filteredRecords = new ArrayList<>();
        for (CSVRecord record : records) {
            double value = Double.parseDouble(record.get(columnName));
            if (value >= lowerBound && value <= upperBound) {
                filteredRecords.add(record);
            }
        }

        return filteredRecords;
    }

    private static double getPercentile(List<Double> values, double percentile) {
        values.sort(Double::compareTo);
        int index = (int) Math.ceil(percentile / 100.0 * values.size());
        return values.get(index - 1);
    }
}

六、数据类型转换

1. 检查数据类型

java 复制代码
import java.util.List;

public class DataTypeChecker {

    public static void checkDataTypes(List<CSVRecord> records, String columnName) {
        for (CSVRecord record : records) {
            String field = record.get(columnName);
            try {
                Integer.parseInt(field);
                System.out.println("Field " + field + " is of type Integer");
            } catch (NumberFormatException e) {
                try {
                    Double.parseDouble(field);
                    System.out.println("Field " + field + " is of type Double");
                } catch (NumberFormatException ex) {
                    System.out.println("Field " + field + " is of type String");
                }
            }
        }
    }
}

2. 转换数据类型

java 复制代码
import java.util.List;

public class DataTypeConverter {

    public static void convertToDouble(List<CSVRecord> records, String columnName) {
        for (CSVRecord record : records) {
            String value = record.get(columnName);
            try {
                double doubleValue = Double.parseDouble(value);
                record.toMap().put(columnName, String.valueOf(doubleValue));
            } catch (NumberFormatException e) {
                System.err.println("Failed to convert " + value + " to Double");
            }
        }
    }
}

七、数据标准化与规范化

1. 标准化

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class DataNormalizer {

    public static void standardizeData(List<CSVRecord> records, String columnName) {
        List<Double> values = new ArrayList<>();
        for (CSVRecord record : records) {
            values.add(Double.parseDouble(record.get(columnName)));
        }

        double mean = values.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
        double stdDev = Math.sqrt(values.stream().mapToDouble(v -> Math.pow(v - mean, 2)).average().orElse(0.0));

        for (CSVRecord record : records) {
            double value = Double.parseDouble(record.get(columnName));
            double standardizedValue = (value - mean) / stdDev;
            record.toMap().put(columnName, String.valueOf(standardizedValue));
        }
    }
}

2. 规范化

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class DataNormalizer {

    public static void normalizeData(List<CSVRecord> records, String columnName) {
        List<Double> values = new ArrayList<>();
        for (CSVRecord record : records) {
            values.add(Double.parseDouble(record.get(columnName)));
        }

        double min = values.stream().min(Double::compareTo).orElse(0.0);
        double max = values.stream().max(Double::compareTo).orElse(1.0);

        for (CSVRecord record : records) {
            double value = Double.parseDouble(record.get(columnName));
            double normalizedValue = (value - min) / (max - min);
            record.toMap().put(columnName, String.valueOf(normalizedValue));
        }
    }
}

八、保存清洗后的数据

java 复制代码
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;

import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

public class DataSaver {

    public static void saveData(String filePath, List<CSVRecord> records) {
        try (FileWriter writer = new FileWriter(filePath);
             CSVPrinter printer = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader(records.get(0).toMap().keySet().toArray(new String[0])))) {

            for (CSVRecord record : records) {
                printer.printRecord(record.toMap().values());
            }
        } catch (IOException e) {
            System.err.println("Failed to save data: " + e.getMessage());
        }
    }
}
相关推荐
止语Lab28 分钟前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活28 分钟前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困33 分钟前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn34 分钟前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
用户2986985301440 分钟前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
用户772831049084042 分钟前
krono-job:零侵入、单二进制交付的分布式任务调度平台(开源)
后端
Conan在掘金1 小时前
鸿蒙报错速查:Function lacks ending return statement,返回路径漏 return 就炸,根因 + 真解法
后端
人间凡尔赛1 小时前
AI-Native 云原生架构:2026 年从容器编排到智能体编排的范式革命
后端·云原生·架构
IT_陈寒2 小时前
Vue的响应式让我加班到凌晨3点,原来问题出在这
前端·人工智能·后端
卷无止境2 小时前
提升 Python 代码健壮性的方法大盘点
后端·python