环境:虚拟机hive+本地spark+python(pyspark)
数据:商品订单数据+商品种类数据
步骤:将数据上传到hdfs后,在python中完成hive表的创建,数据处理,关联规则挖掘,数据可视化
实现功能:对商品订单中的信息进行挖掘,得到商品组合之间的关联关系(本文只对order进行了处理,没有涉及到type)
一.数据准备
将GoodsOrder.csv和GoodsTypes.csv文件上传到hdfs创建的数据文件夹
hdfs dfs -mkdir /hive_data/homework/data/order
hdfs dfs -mkdir /hive_data/homework/data/type
hdfs dfs -put /export/data/hive_data/GoodsOrder.csv /hive_data/homework/data/order
hdfs dfs -put /export/data/hive_data/GoodsTypes.csv /hive_data/homework/data/type
二.pyspark创建hive表
前提是已经完成了本地spark连接虚拟机hive的操作,见前文
而且这里有个小坑,spark直接删除hive表的话,只会删除表的元数据,不会删除表的数据文件,如果直接使用spark.sql(“drop..”)的话,在后面重新创建同名hive表的话,就会一直提示某某文件夹已存在,所以我查了一下可以直接去hive中删除,或者在spark中使用以下命令删除
spark.sql("ALTER TABLE homework.type SET TBLPROPERTIES ('external.table.purge'='true')")
spark.sql("drop table homework.type")
创建hive表--order和type
def createTable():
spark = SparkSession \
.builder \
.appName("Python Spark SQL Hive integration example") \
.enableHiveSupport() \
.getOrCreate()
spark.sql("show databases").show()
# 创建数据库不指定location,则默认创建在hive.metastore.warehouse.dir设置的文件夹中,这个在hive-site.xml中设置
spark.sql("create database IF NOT EXISTS homework")
'''
数据文件通过hdfs命令,hdfs dfs -put /export/data/hive_data/download.csv /hive_data/homework/data
由虚拟机上传到hdfs的/hive_data/homework/data文件夹下,
访问的前缀在hadoop的core-site.xml文件中设置,值为hdfs://master,master对应为node01和node02,
具体的选择由Zookeeper完成,使用status命令查看哪一台虚拟机被选举为leader,当前是node2为leader,
因此通过下面的地址就可以访问到hdfs文件系统(端口号为9000)
注意建表语句的中表的数据格式要与导入的数据一致
而且要注意加上分隔符的设置,否则导入都为null
'''
spark.sql("use homework")
spark.sql("CREATE EXTERNAL TABLE IF NOT EXISTS homework.order(id INT,good STRING) "
"ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION "
"'hdfs://192.168.121.131:9000/hive_data/homework/data/order'")
spark.sql("select * from homework.order").show()
spark.sql("CREATE EXTERNAL TABLE IF NOT EXISTS homework.type(good STRING,type STRING) "
"ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION "
"'hdfs://192.168.121.131:9000/hive_data/homework/data/type'")
spark.sql("show tables").show()
spark.sql("select * from homework.type").show()
PS:如果发现select结果是乱码,那么很大的可能是因为csv文件没有保存为utf-8,修改格式后删除hdfs上的文件并重新上传修改后的文件,删除hive表后重新导入,即可解决乱码
成功创建
三.pyspark数据处理
使用的关联规则算法是Apriori,这里通过mlxtend库实现,因为它提供了支持度,更加详细,因此就需要先把order表中的数据转换成需要的列表格式。
# 按照id进行聚合,Goods_list存储每个订单中的商品
order_list = order.groupBy("id").agg(F.collect_list("good").alias("Goods_list"))
order_list.show()
# 将Goods_list列的内容取出存入good_list列表
Goods_list = order_list.select("Goods_list").collect()
good_list = []
for i in Goods_list:
good_list.append(i["Goods_list"])
四.关联规则挖掘
这里研究订单的商品之间的关联规则,也就是说用户在购买了某一个商品的同时,购买另一个商品的概率。通过设置支持度和置信度得到合适的结果、支持度大于一表示正相关,小于一表示负相关。
'''
2.关联规则挖掘
'''
TE = TransactionEncoder() # 构造转换模型
data = TE.fit_transform(good_list) # 将原始数据转换为bool型
df = pd.DataFrame(data, columns=TE.columns_) # 使用DataFrame存储bool数据
item_set = apriori(df, min_support=0.05, use_colnames=True) # 设置最小支持度参数
print(item_set)
# 提示:Empty DataFrame----可能是没有超过该阈值的频繁项目,因此item_set为空,rules调用出错
rules = association_rules(item_set, min_threshold=0.2) # 设置最小置信度,根据最小置信度在频繁项集中产生强关联规则
pd.set_option('expand_frame_repr', False)
print(rules)
data_a = [] # 柱状图的横坐标,记录关联关系
data_b = [] # 关联的第一个柱,表示置信度
data_c = [] # 关联的第二个柱,表示提升度
for i, j in rules.iterrows(): # 'for index, row in dataset.iterrows():'index是行索引值,row是对应的行内容
X = j['antecedents']
Y = j['consequents']
Z = j['confidence']
U = j['lift']
x = ','.join([item for item in X])
y = ','.join([item for item in Y])
xy = x + "→" + y
print(xy + " 置信度=" + str(Z) + " 提升度=" + str(U))
data_a.append(xy)
data_b.append(Z)
data_c.append(U)
五.关联情况可视化
# 绘制柱状图
plt.rcParams['font.sans-serif'] = ["SimHei"] # 不支持中文,所以进行临时设置
size = len(data_a)
place = np.arange(size) # 根据数据个数生成柱子的中点位置,也是放置横轴数据的位置
# 1.设置横轴
plt.figure(figsize=(15, 12), dpi=200)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.set_xticks(place) # x轴的位置
ax.set_xticklabels(data_a, rotation=0, fontsize=10) # x轴
ax.set_xlabel('关联规则') # x轴名称
# 2.设置两个柱
total_width, n = 0.8, 2 # n表示柱子的种类数
width = total_width / n # 得到每个柱子的宽度
place = place - (total_width - width) / 2 # 得到柱子的每个起始位置
plt.bar(place, data_b, width=width, label='置信度') # 柱1
plt.bar(place + width, data_c, width=width, label='提升度') # 柱2
# 3.设置数字在柱上显示
for i in range(size):
plt.text(place[i], data_b[i] + 0.01, '%.3f' % data_b[i], ha='center', va='bottom',
fontsize=10) # 设置在柱1的顶部显示数字--保留三位小数,在柱子上方0.01处居中显示
plt.text(place[i] + width, data_c[i] + 0.01, '%.3f' % data_c[i], ha='center', va='bottom',
fontsize=10) # 设置在柱2的顶部显示数字
plt.legend()
plt.show()
六.完整代码以及数据文件
七.总结
通过关联规则挖掘,可以对商品的摆放提供参考,例如酸奶和全脂牛奶可以一起摆放,同时也可以结合商品种类,对于不同种类的商品摆放提供参考。