数据整理

本文介绍了如何使用Spark进行数据预处理,包括配置Spark环境、读取HDFS数据、数据清洗、列类型转换、热独编码等步骤。通过分析原始数据,确定了关键特征并进行了编码处理,为后续的模型训练做准备。
摘要由CSDN通过智能技术生成

8.1 分析并预处理raw_sample数据集
import os

配置spark driver和pyspark运行时,所使用的python解释器路径

PYSPARK_PYTHON = “/root/miniconda3/bin/python3”
os.environ[“PYSPARK_PYTHON”] = PYSPARK_PYTHON
os.environ[“PYSPARK_DRIVER_PYTHON”] = PYSPARK_PYTHON

spark配置信息

from pyspark import SparkConf
from pyspark.sql import SparkSession

SPARK_APP_NAME = “preprocessingRawSample”
SPARK_URL = “spark://192.168.199.126:7077”

conf = SparkConf() # 创建spark config对象
config = (
(“spark.app.name”, SPARK_APP_NAME), # 设置启动的spark的app名称,没有提供,将随机产生一个名称
(“spark.executor.memory”, “2g”), # 设置该app启动时占用的内存用量,默认1g
(“spark.master”, SPARK_URL), # spark master的地址
(“spark.executor.cores”, “2”) # 设置spark executor使用的CPU核心数

(‘spark.sql.pivotMaxValues’, ‘99999’), # 当需要pivot DF,且值很多时,需要修改,默认是10000

)

查看更详细配置及说明:https://spark.apache.org/docs/latest/configuration.html

conf.setAll(config)

利用config对象,创建spark session

spark = SparkSession.builder.config(conf=conf).getOrCreate()

从HDFS中加载样本数据信息

df = spark.read.csv(“file:///root/jupyter_code/raw_sample.csv”, header=True)
df.show() # 展示数据,默认前20条
df.printSchema()
显示结果:

±-----±---------±---------±----------±-----±–+
| user|time_stamp|adgroup_id| pid|nonclk|clk|
±-----±---------±---------±----------±-----±–+
|581738|1494137644| 1|430548_1007| 1| 0|
|449818|1494638778| 3|430548_1007| 1| 0|
|914836|1494650879| 4|430548_1007| 1| 0|
|914836|1494651029| 5|430548_1007| 1| 0|
|399907|1494302958| 8|430548_1007| 1| 0|
|628137|1494524935| 9|430548_1007| 1| 0|
|298139|1494462593| 9|430539_1007| 1| 0|
|775475|1494561036| 9|430548_1007| 1| 0|
|555266|1494307136| 11|430539_1007| 1| 0|
|117840|1494036743| 11|430548_1007| 1| 0|
|739815|1494115387| 11|430539_1007| 1| 0|
|623911|1494625301| 11|430548_1007| 1| 0|
|623911|1494451608| 11|430548_1007| 1| 0|
|421590|1494034144| 11|430548_1007| 1| 0|
|976358|1494156949| 13|430548_1007| 1| 0|
|286630|1494218579| 13|430539_1007| 1| 0|
|286630|1494289247| 13|430539_1007| 1| 0|
|771431|1494153867| 13|430548_1007| 1| 0|
|707120|1494220810| 13|430548_1007| 1| 0|
|530454|1494293746| 13|430548_1007| 1| 0|
±-----±---------±---------±----------±-----±–+
only showing top 20 rows

root
|-- user: string (nullable = true)
|-- time_stamp: string (nullable = true)
|-- adgroup_id: string (nullable = true)
|-- pid: string (nullable = true)
|-- nonclk: string (nullable = true)
|-- clk: string (nullable = true)
分析数据集字段的类型和格式
查看是否有空值
查看每列数据的类型
查看每列数据的类别情况
print(“样本数据集总条目数:”, df.count())

约2600w

print(“用户user总数:”, df.groupBy(“user”).count().count())

约 114w,略多余日志数据中用户数

print(“广告id adgroup_id总数:”, df.groupBy(“adgroup_id”).count().count())

约85w

print(“广告展示位pid情况:”, df.groupBy(“pid”).count().collect())

只有两种广告展示位,占比约为六比四

print(“广告点击数据情况clk:”, df.groupBy(“clk”).count().collect())

点和不点比率约: 1:20

显示结果:

样本数据集总条目数: 26557961
用户user总数: 1141729
广告id adgroup_id总数: 846811
广告展示位pid情况: [Row(pid=‘430548_1007’, count=16472898), Row(pid=‘430539_1007’, count=10085063)]
广告点击数据情况clk: [Row(clk=‘0’, count=25191905), Row(clk=‘1’, count=1366056)]
使用dataframe.withColumn更改df列数据结构;使用dataframe.withColumnRenamed更改列名称

更改表结构,转换为对应的数据类型

from pyspark.sql.types import StructType, StructField, IntegerType, FloatType, LongType, StringType

打印df结构信息

df.printSchema()

更改df表结构:更改列类型和列名称

raw_sample_df = df.
withColumn(“user”, df.user.cast(IntegerType())).withColumnRenamed(“user”, “userId”).
withColumn(“time_stamp”, df.time_stamp.cast(LongType())).withColumnRenamed(“time_stamp”, “timestamp”).
withColumn(“adgroup_id”, df.adgroup_id.cast(IntegerType())).withColumnRenamed(“adgroup_id”, “adgroupId”).
withColumn(“pid”, df.pid.cast(StringType())).
withColumn(“nonclk”, df.nonclk.cast(IntegerType())).
withColumn(“clk”, df.clk.cast(IntegerType()))
raw_sample_df.printSchema()
raw_sample_df.show()
显示结果:

root
|-- user: string (nullable = true)
|-- time_stamp: string (nullable = true)
|-- adgroup_id: string (nullable = true)
|-- pid: string (nullable = true)
|-- nonclk: string (nullable = true)
|-- clk: string (nullable = true)

root
|-- userId: integer (nullable = true)
|-- timestamp: long (nullable = true)
|-- adgroupId: integer (nullable = true)
|-- pid: string (nullable = true)
|-- nonclk: integer (nullable = true)
|-- clk: integer (nullable = true)

±-----±---------±--------±----------±-----±–+
|userId| timestamp|adgroupId| pid|nonclk|clk|
±-----±---------±--------±----------±-----±–+
|581738|1494137644| 1|430548_1007| 1| 0|
|449818|1494638778| 3|430548_1007| 1| 0|
|914836|1494650879| 4|430548_1007| 1| 0|
|914836|1494651029| 5|430548_1007| 1| 0|
|399907|1494302958| 8|430548_1007| 1| 0|
|628137|1494524935| 9|430548_1007| 1| 0|
|298139|1494462593| 9|430539_1007| 1| 0|
|775475|1494561036| 9|430548_1007| 1| 0|
|555266|1494307136| 11|430539_1007| 1| 0|
|117840|1494036743| 11|430548_1007| 1| 0|
|739815|1494115387| 11|430539_1007| 1| 0|
|623911|1494625301| 11|430548_1007| 1| 0|
|623911|1494451608| 11|430548_1007| 1| 0|
|421590|1494034144| 11|430548_1007| 1| 0|
|976358|1494156949| 13|430548_1007| 1| 0|
|286630|1494218579| 13|430539_1007| 1| 0|
|286630|1494289247| 13|430539_1007| 1| 0|
|771431|1494153867| 13|430548_1007| 1| 0|
|707120|1494220810| 13|430548_1007| 1| 0|
|530454|1494293746| 13|430548_1007| 1| 0|
±-----±---------±--------±----------±-----±–+
only showing top 20 rows
特征选取(Feature Selection)

特征选择就是选择那些靠谱的Feature,去掉冗余的Feature,对于搜索广告,Query关键词和广告的匹配程度很重要;但对于展示广告,广告本身的历史表现,往往是最重要的Feature。

根据经验,该数据集中,只有广告展示位pid对比较重要,且数据不同数据之间的占比约为6:4,因此pid可以作为一个关键特征

nonclk和clk在这里是作为目标值,不做为特征

热独编码 OneHotEncode

热独编码是一种经典编码,是使用N位状态寄存器(如0和1)来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候,其中只有一位有效。

假设有三组特征,分别表示年龄,城市,设备;

[“男”, “女”][0,1]

[“北京”, “上海”, “广州”][0,1,2]

[“苹果”, “小米”, “华为”, “微软”][0,1,2,3]

传统变化: 对每一组特征,使用枚举类型,从0开始;

["男“,”上海“,”小米“]=[ 0,1,1]

["女“,”北京“,”苹果“] =[1,0,0]

传统变化后的数据不是连续的,而是随机分配的,不容易应用在分类器中

而经过热独编码,数据会变成稀疏的,方便分类器处理:

["男“,”上海“,”小米“]=[ 1,0,0,1,0,0,1,0,0]

["女“,”北京“,”苹果“] =[0,1,1,0,0,1,0,0,0]

这样做保留了特征的多样性,但是也要注意如果数据过于稀疏(样本较少、维度过高),其效果反而会变差

Spark中使用热独编码

注意:热编码只能对字符串类型的列数据进行处理

StringIndexer:对指定字符串列数据进行特征处理,如将性别数据“男”、“女”转化为0和1

OneHotEncoder:对特征列数据,进行热编码,通常需结合StringIndexer一起使用

Pipeline:让数据按顺序依次被处理,将前一次的处理结果作为下一次的输入

特征处理

‘’‘特征处理’’’
‘’’
pid 资源位。该特征属于分类特征,只有两类取值,因此考虑进行热编码处理即可,分为是否在资源位1、是否在资源位2 两个特征
‘’’
from pyspark.ml.feature import OneHotEncoder
from pyspark.ml.feature import StringIndexer
from pyspark.ml import Pipeline

StringIndexer对指定字符串列进行特征处理

stringindexer = StringIndexer(inputCol=‘pid’, outputCol=‘pid_feature’)

对处理出来的特征处理列进行,热独编码

encoder = OneHotEncoder(dropLast=False, inputCol=‘pid_feature’, outputCol=‘pid_value’)

利用管道对每一个数据进行热独编码处理

pipeline = Pipeline(stages=[stringindexer, encoder])
pipeline_model = pipeline.fit(raw_sample_df)
new_df = pipeline_model.transform(raw_sample_df)
new_df.show()
显示结果:

±-----±---------±--------±----------±-----±–±----------±------------+
|userId| timestamp|adgroupId| pid|nonclk|clk|pid_feature| pid_value|
±-----±---------±--------±----------±-----±–±----------±------------+
|581738|1494137644| 1|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|449818|1494638778| 3|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|914836|1494650879| 4|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|914836|1494651029| 5|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|399907|1494302958| 8|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|628137|1494524935| 9|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|298139|1494462593| 9|430539_1007| 1| 0| 1.0|(2,[1],[1.0])|
|775475|1494561036| 9|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|555266|1494307136| 11|430539_1007| 1| 0| 1.0|(2,[1],[1.0])|
|117840|1494036743| 11|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|739815|1494115387| 11|430539_1007| 1| 0| 1.0|(2,[1],[1.0])|
|623911|1494625301| 11|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|623911|1494451608| 11|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|421590|1494034144| 11|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|976358|1494156949| 13|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|286630|1494218579| 13|430539_1007| 1| 0| 1.0|(2,[1],[1.0])|
|286630|1494289247| 13|430539_1007| 1| 0| 1.0|(2,[1],[1.0])|
|771431|1494153867| 13|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|707120|1494220810| 13|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|530454|1494293746| 13|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
±-----±---------±--------±----------±-----±–±----------±------------+
only showing top 20 rows
返回字段pid_value是一个稀疏向量类型数据 pyspark.ml.linalg.SparseVe

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值