数据清洗
一、背景
在数仓项目中,数据经常不是我们想要的,数据可能存在不完整的情况,或有一些null,或者格式不对,那么我们需要对数据进行清洗。
'一条数据'
barelypolitical 151 5106
'每个字段代表的含义'
uploader:barelypolitical
videos: 151
friends: 5106
'一条数据':
LKh7zAJ4nwo TheReceptionist 653 Entertainment 424 13021 4.34 1305 744 DjdA-5oKYFQ NxTDlnOuybo
c-8VuICzXtU DH56yrIO5nI
'每个字段代表的含义':
'videoId':LKh7zAJ4nwo
'uploader':TheReceptionist
'age':653
'category':People & Blogs
'length':424
'views':13021
'rate':4.34
'Ratings':1305
'conments':744
'relatedId':DjdA-5oKYFQ NxTDlnOuybo c-8VuICzXtU DH56yrIO5nI
1. 格式转换成统一的格式
视频类别的分隔符和相关视频的id两个数据格式进行处理。
2. 进行一些数据处理,数据格式不完整的不要。
字段 | 备注 | 详细描述 |
---|
videoId | 视频唯一id(String) | 11位字符串 |
uploader | 视频上传者(String) | 上传视频的用户名String |
age | 视频年龄(int) | 视频在平台上的整数天 |
category | 视频类别(Array) | 上传视频指定的视频分类 |
length | 视频长度(Int) | 整形数字标识的视频长度 |
views | 观看次数(Int) | 视频被浏览的次数 |
rate | 视频评分(Double) | 满分5分 |
Ratings | 流量(Int) | 视频的流量,整型数字 |
conments | 评论数(Int) | 一个视频的整数评论数 |
relatedId | 相关视频id(Array) | 相关视频的id,最多20个 |
*字段* | *备注* | *字段类型* |
---|
uploader | 上传者用户名 | string |
videos | 上传视频数 | int |
friends | 朋友数量 | int |
二、数据清洗思想
a、 数据长度小于9的不要
b、 将数据中的视频类别中间的空格去掉 People & Blogs
c、 将数据中的关联视频id通过&符号拼接
三、代码实现
3.0 准备工作
- 添加依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.1.3</version>
</dependency>
</dependencies>
- 在resource目录下创建一个log4j2.xml文件,并添加如下配置内容
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error" strict="true" name="XMLConfig">
<Appenders>
<Appender type="Console" name="STDOUT">
<Layout type="PatternLayout"
pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss}][%c{10}]%m%n" />
</Appender>
</Appenders>
<Loggers>
<Logger name="test" level="info" additivity="false">
<AppenderRef ref="STDOUT" />
</Logger>
<Root level="info">
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>
3.1 创建一个工具类
public class ETLUtils {
public static String etlData(String srcData){
StringBuffer resultData = new StringBuffer();
String[] datas = srcData.split("\t");
if(datas.length <9){
return null ;
}
datas[3]=datas[3].replaceAll(" ","");
for (int i = 0; i < datas.length; i++) {
if(i < 9){
if(i == datas.length-1){
resultData.append(datas[i]);
}else{
resultData.append(datas[i]).append("\t");
}
}else{
if(i == datas.length-1){
resultData.append(datas[i]);
}else{
resultData.append(datas[i]).append("&");
}
}
}
return resultData.toString();
}
}
3.2 创建mapper类
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
public class ETLMapper extends Mapper<LongWritable, Text, Text, NullWritable> {
private Text k = new Text();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
String resultData = ETLUtils.etlData(line);
if(resultData != null) {
k.set(resultData);
context.write(k,NullWritable.get());
}
}
}
3.3 创建driver类
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class ETLDriver {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
job.setJarByClass(ETLDriver.class);
job.setMapperClass(ETLMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(NullWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class);
job.setNumReduceTasks(0);
FileInputFormat.setInputPaths(job,new Path(args[0]));
FileOutputFormat.setOutputPath(job,new Path(args[1]));
job.waitForCompletion(true);
}
}
四、代码打包
将ETL程序打包为etl.jar 并上传到Linux的 /opt/module/hive/datas 目录下