1.分析并预处理raw_sample数据集
1.1 查看与分析
# 从HDFS中加载样本数据信息
df = spark.read.csv("hdsf://localhost:9000/datasets/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)
- 分析数据集字段的类型和格式
1.查看是否有空值
2.查看每列数据的类型
3.查看每列数据的类别情况
print("样本数据集总条目数:", df.count())
print("用户user总数:", df.groupBy("user").count().count())
print("广告id adgroup_id总数:", df.groupBy("adgroup_id").count().count())
print("广告展示位pid情况:", groupBy("pid").count().count())
print("广告点击数据情况clk:", groupBy("clk").count().collect())
显示结果:
样本数据集总条目数: 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)]
1.2 更改结构
- 使用dataframe.withColumn更改df列数据结构;使用dataframe.withColumeRenamed更改列名称
# 更改表结构,转换为对应的数据类型
from pyspark.sql.types import StructType, StructFiled, IntergerType, 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()
显示结果:
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)
- 独热编码OneHotEncode:对分类特征,按(0,1)的形式,有该分类标记1,无则标记0,处理后,数据会变稀疏,这样做保留了特征的多样性
- Spark中使用独热编码:
1.StringIndexer:对指定字符串列数据进行特征处理,如:将性别数据“男”,“女”转化为0,1
2.OneHotEncoder:对特征列数据,进行独热编码,通常与StringIndexer一起使用
3.Pipeline:让数据按顺序依次被处理,将前一次的处理结果作为下一次的输入
1.3 特征处理
"""特征处理"""
"""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是一个稀疏向量类型数据
1.4 数据集划分
- 查看最大时间
new_df.sort("timestamp", ascending=False).show()
显示结果:
+------+----------+---------+-----------+------+---+-----------+-------------+
|userId| timestamp|adgroupId| pid|nonclk|clk|pid_feature| pid_value|
+------+----------+---------+-----------+------+---+-----------+-------------+
|177002|1494691186| 593001|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|243671|1494691186| 600195|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|488527|1494691184| 494312|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|488527|1494691184| 431082|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
| 17054|1494691184| 742741|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
| 17054|1494691184| 756665|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|488527|1494691184| 687854|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|839493|1494691183| 561681|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|704223|1494691183| 624504|430539_1007| 1| 0| 1.0|(2,[1],[1.0])|
|839493|1494691183| 582235|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|704223|1494691183| 675674|430539_1007| 1| 0| 1.0|(2,[1],[1.0])|
|628998|1494691180| 618965|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|674444|1494691179| 427579|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|627200|1494691179| 782038|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|627200|1494691179| 420769|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|674444|1494691179| 588664|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|738335|1494691179| 451004|430539_1007| 1| 0| 1.0|(2,[1],[1.0])|
|627200|1494691179| 817569|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|322244|1494691179| 820018|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
|322244|1494691179| 735220|430548_1007| 1| 0| 0.0|(2,[0],[1.0])|
+------+----------+---------+-----------+------+---+-----------+-------------+
only showing top 20 rows
# 本样本数据集共计8天数据
# 前七天为训练数据,最后一天为测试数据
from datetime import datetime
print("该时间之前的数据为训练样本,该时间以后的数据为测试样本:", datetime.fromtimestamp(1494691179-24*60*60)
显示结果:
该时间之前的数据为训练样本,该时间以后的数据为测试样本: 2017-05-12 23:59:46
# 训练样本:
train_sample = raw_sample_df.filter(raw_sample_df.timestamp<=(1494691179-24*60*60))
print("训练样本个数:")
print(train_sample.count())
# 测试样本
test_sample = raw_sample_df.filter(raw_sample_df.timestamp>(1494691179-24*60*60))
print("测试样本个数:")
print(test_sample.count())
# 注意:还需要加入广告基本特征和用户基本特征才能做成一份完整的样本数据集
显示结果:
训练样本个数:
23249291
测试样本个数:
3308670