矿大京-大数据技术实验课-spark+Python数据分析

本文主要用于解决实验报告中2/3/4/6四道题目

第五题和第七题是直接按照实验报告来做即可,没有编程要求。

基于jupyter notebook来写,并且实验数据自行准备,学号为双号,单号仅供参考

代码是第一次写的复杂版本(屎山代码.bushi),非本人最终版本,但运行结果一致。

实验报告不要求可视化部分,可忽略。

初版,后续可能精修,看心情。

最近在搭自己的博客,忙着想方设法的睡觉,时间很不充裕。

首先需要在jupyter notebook里下载好spark库

​
!pip install pyspark --user

注意,Linux虚拟机中是需要开启spark的,启动spark后新建一个终端启动jupyter然后在浏览器特定端口下用jupyter进行数据分析。

实验内容与步骤

第二题

2 音乐数据的spark+python分析(https://dblab.xmu.edu.cn/blog/2744/,基于Spark的音乐专辑数据分析展示python)

(1)查询滚石网站、MTV、音乐达人三者评分合计最高的前10条专辑信息,按评分降序排列(代码与结果截图);

(2)总销量前6的专辑类型,在不同评分体系中的平均评分(按销量降序排列)。

from pyspark.sql import SparkSession
from pyspark.sql.functions import col, sum as _sum, avg
import matplotlib.pyplot as plt

# 初始化Spark会话
spark = SparkSession.builder.appName("Music Album Analysis").getOrCreate()

# 加载数据
df = spark.read.csv("C:/Users/安全工程4班王鑫/Desktop/虚拟机软件/music-analysis/albums.csv", header=True, inferSchema=True)

# 计算每个专辑的总评分
df_with_scores = df.withColumn("total_critic_score", col("rolling_stone_critic") + col("mtv_critic") + col("music_maniac_critic"))

# 找出总评分最高的前10个专辑
top_albums = df_with_scores.orderBy(col("total_critic_score").desc()).limit(10)

# 显示前10个专辑的表格
top_albums.show()

# 将Spark DataFrame转换为Pandas DataFrame用于可视化
top_albums_pandas = top_albums.toPandas()

# 使用Matplotlib进行可视化
plt.figure(figsize=(10, 6))
plt.barh(top_albums_pandas['album_title'], top_albums_pandas['total_critic_score'])
plt.xlabel('Total Critic Score')
plt.ylabel('Album Title')
plt.title('Top 10 Albums Based on Critic Scores')
plt.gca().invert_yaxis()
plt.show()

# 计算总销量前6的专辑类型
genre_sales = df.groupBy("genre").agg(_sum("num_of_sales").alias("total_sales")).orderBy(col("total_sales").desc()).limit(6)

# 计算这些顶级类型的平均评分
top_genres_scores = df.join(genre_sales, "genre").groupBy("genre").agg(avg("rolling_stone_critic").alias("avg_rolling_stone"), avg("mtv_critic").alias("avg_mtv"), avg("music_maniac_critic").alias("avg_music_maniac"))

# 显示这些顶级类型的评分表格
top_genres_scores.show()

# 将结果转换为Pandas DataFrame用于可视化
top_genres_scores_pandas = top_genres_scores.toPandas()

# 绘制每个评分体系的平均评分
top_genres_scores_pandas.plot(kind='bar', x='genre', y=['avg_rolling_stone', 'avg_mtv', 'avg_music_maniac'], figsize=(10, 6))
plt.ylabel('Average Score')
plt.title('Average Scores by Genre in Top Selling Genres')
plt.show()

# 关闭Spark会话
spark.stop()

再次强调虽然能得出正确结果但是是不符合要求的非精修形式

请自行修改表示形式,以表格的形式展现

可视化版代码结果:

精修版本结果:再次注意:老师不要求进行可视化。

(代码因为是本人自用的怕查重,就不贴上去了,也不要来问我,我不给 X ~L~ X)

第三题

3 淘宝数据的spark+python分析(https://dblab.xmu.edu.cn/blog/3525/,基于Spark的淘宝数据分析scala)

(1)销量前5的日期,降序排列;(双号)

2销量前5的小时,降序排列;

3购买合计/收藏合计 的比例;(双号)

代码:

from pyspark.sql import SparkSession
from pyspark.sql.functions import col, hour, count, when
import matplotlib.pyplot as plt

spark = SparkSession.builder.appName("Taobao Data Analysis").getOrCreate()
df = spark.read.option("header", "true").csv("C:/Users/安全工程4班王鑫/Desktop/虚拟机软件/Processed_UserBehavior.csv")

# 使用 Spark SQL 函数处理日期和时间
df = df.withColumn("date", col("day"))
df = df.withColumn("hour", hour("time"))

# (1) 销量前5的日期,降序排列
sales_by_date = df.filter(col("action") == "buy").groupBy("date").agg(count("*").alias("total_sales"))
top5_sales_dates = sales_by_date.orderBy(col("total_sales").desc()).limit(5)

# 展示销量前5的日期
top5_sales_dates.show()

# 可视化销量前5的日期 - 折线图
top5_sales_dates_pd = top5_sales_dates.toPandas()
top5_sales_dates_pd.sort_values('date', inplace=True)
plt.figure(figsize=(10, 6))
plt.plot(top5_sales_dates_pd['date'], top5_sales_dates_pd['total_sales'], marker='o')
plt.xlabel('Date')
plt.ylabel('Total Sales')
plt.title('Top 5 Sales Dates')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

# (2) 销量前5的小时,降序排列
sales_by_hour = df.filter(col("action") == "buy").groupBy("hour").agg(count("*").alias("total_sales"))
top5_sales_hours = sales_by_hour.orderBy(col("total_sales").desc()).limit(5)

# 展示销量前5的小时
top5_sales_hours.show()

# 可视化销量前5的小时 - 折线图
top5_sales_hours_pd = top5_sales_hours.toPandas()
top5_sales_hours_pd.sort_values('hour', inplace=True)
plt.figure(figsize=(10, 6))
plt.plot(top5_sales_hours_pd['hour'], top5_sales_hours_pd['total_sales'], marker='o')
plt.xlabel('Hour of the Day')
plt.ylabel('Total Sales')
plt.title('Sales by Hour')
plt.xticks(range(0, 24))
plt.grid(True)
plt.tight_layout()
plt.show()

# (3) 购买合计/收藏合计 的比例
purchase_count = df.filter(col("action") == "buy").count()
favorite_count = df.filter(col("action") == "fav").count()
purchase_to_favorite_ratio = [
    ('Purchase', purchase_count),
    ('Favorite', favorite_count - purchase_count) 
]

# 展示购买与收藏的比例
print(f"Purchase to Favorite Ratio: {purchase_favorite_ratio}")

# 可视化购买与收藏的比例 - 饼图
labels = [x[0] for x in purchase_to_favorite_ratio]
sizes = [x[1] for x in purchase_to_favorite_ratio]
plt.figure(figsize=(8, 8))
plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=140)
plt.title('Purchase to Favorite Ratio')
plt.show()

# 关闭Spark会话
spark.stop()

运行结果:

第四题

4 碳排放数据的Spark+Python分析(https://dblab.xmu.edu.cn/blog/4400/,基于CO2排放量数据集的数据分析及可视化python)

(1)2011-2021年平均排放量最高的前5个国家与平均排放量;(双号)

(2)在2016-2021年中,中国Gas、Oil、Coal排放量比例;(双号)

代码:

from pyspark.sql import SparkSession
from pyspark.sql.functions import col, avg
import matplotlib.pyplot as plt
spark = SparkSession.builder.appName("CO2 Emissions Analysis").getOrCreate()
data_path = "C:/Users/安全工程4班王鑫/Desktop/虚拟机软件/GCB2022v27_MtCO2_flat.csv"
df = spark.read.option("header", "true").csv(data_path)

# 数据清洗:过滤出2011-2021年的数据,并转换为合适的数据类型
df_clean = df.filter((col("Year") >= 2011) & (col("Year") <= 2021))
df_clean = df_clean.withColumn("Total", col("Total").cast("float"))
df_clean = df_clean.withColumn("Coal", col("Coal").cast("float"))
df_clean = df_clean.withColumn("Oil", col("Oil").cast("float"))
df_clean = df_clean.withColumn("Gas", col("Gas").cast("float"))

# (1) 2011-2021年平均排放量最高的前5个国家与平均排放量
avg_emissions_by_country = df_clean.groupBy("Country").agg(avg("Total").alias("Avg_Total"))
top5_countries = avg_emissions_by_country.orderBy(col("Avg_Total").desc()).limit(6)

# 展示平均排放量最高的前5个国家
top5_countries.show()

# 可视化平均排放量最高的前5个国家 - 柱状图
top5_countries_pd = top5_countries.toPandas()
plt.figure(figsize=(10, 6))
top5_countries_pd.plot(kind='bar', x='Country', y='Avg_Total', legend=None)
plt.xlabel('Country')
plt.ylabel('Average Total Emissions')
plt.title('Top 5 Countries by Average CO2 Emissions (2011-2021)')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

# (2) 在2016-2021年中,中国Gas、Oil、Coal排放量比例
china_df = df_clean.filter((col("Country") == "China") & (col("Year") >= 2016))
china_emissions = china_df.select("Coal", "Oil", "Gas").groupBy().sum().collect()[0]

# 展示中国的Gas、Oil、Coal排放量比例
china_emissions_proportions = {
    "Coal": china_emissions["sum(Coal)"],
    "Oil": china_emissions["sum(Oil)"],
    "Gas": china_emissions["sum(Gas)"]
}

# 可视化中国的Gas、Oil、Coal排放量比例 - 饼图
labels = china_emissions_proportions.keys()
sizes = china_emissions_proportions.values()
plt.figure(figsize=(8, 8))
plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=140)
plt.title('China CO2 Emissions Proportions (2016-2021)')
plt.show()

# 关闭Spark会话
spark.stop()

运行结果:

第五题

第五题对应博客一步一步来即可

https://dblab.xmu.edu.cn/blog/3212/

正确运行结果大概如下

第六题

6 豆瓣电影数据的Spark+Python分析(https://dblab.xmu.edu.cn/blog/2951/,基于Flink的对豆瓣电影数据的分析与处理scala)

(1)每年上映电影数量最多的前三名电影类型,显示年份、电影类型、电影数量。按年份升序、数量降序排列;(双号)

(2)每年平均评分前3的制片国家/地区(双号)

代码:

from pyspark.sql import SparkSession
from pyspark.sql.functions import col, explode, split, avg, count
from pyspark.sql.window import Window
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
import plotly.graph_objects as go
import pandas as pd

spark = SparkSession.builder.appName("Douban Movie Data Analysis").getOrCreate()
movies_df = spark.read.csv("C:/Users/安全工程4班王鑫/Desktop/虚拟机软件/douban_2.csv", header=True, inferSchema=True)
movies_df = movies_df.dropna(subset=["year", "genre", "country", "rating"])
genre_df = movies_df.withColumn("genre", explode(split(col("genre"), "/")))
genre_counts = genre_df.groupBy("year", "genre").count()
window_genre = Window.partitionBy("year").orderBy(col("count").desc())
top_genres_by_year = genre_counts.withColumn("rank", rank().over(window_genre)).filter(col("rank") <= 3)
top_genres_by_year = top_genres_by_year.orderBy("year", col("count").desc())
country_df = movies_df.withColumn("country", explode(split(col("country"), "/")))
country_avg_ratings = country_df.groupBy("year", "country").agg(avg("rating").alias("avg_rating"))
window_country = Window.partitionBy("year").orderBy(col("avg_rating").desc())
top_countries_by_year = country_avg_ratings.withColumn("rank", rank().over(window_country)).filter(col("rank") <= 3)
top_countries_by_year = top_countries_by_year.orderBy("year", col("avg_rating").desc())


# 数据处理和表格创建
top_genres_grouped = top_genres_by_year_pd.groupby(['year', 'rank']).agg({
    'genre': 'first',
    'count': 'first'
}).reset_index()
top_genres_pivot = top_genres_grouped.pivot(index='year', columns='rank', values=['genre', 'count'])
top_genres_pivot.columns = ['_'.join(map(str, col)).strip() for col in top_genres_pivot.columns.values]
top_genres_pivot.rename(columns={
    'genre_1': '数量最多电影类型',
    'count_1': '数量最多电影数量',
    'genre_2': '数量第二电影类型',
    'count_2': '数量第二电影数量',
    'genre_3': '数量第三电影类型',
    'count_3': '数量第三电影数量'
}, inplace=True)
print(top_genres_pivot)
top_countries_grouped = top_countries_by_year_pd.groupby(['year', 'rank']).agg({
    'country': 'first',
    'avg_rating': 'first'
}).reset_index()
top_countries_pivot = top_countries_grouped.pivot(index='year', columns='rank', values=['country', 'avg_rating'])
top_countries_pivot.columns = ['_'.join(map(str, col)).strip() for col in top_countries_pivot.columns.values]
top_countries_pivot.rename(columns={
    'country_1': '平均评分最高国家',
    'avg_rating_1': '平均评分最高值',
    'country_2': '平均评分第二国家',
    'avg_rating_2': '平均评分第二值',
    'country_3': '平均评分第三国家',
    'avg_rating_3': '平均评分第三值'
}, inplace=True)
print(top_countries_pivot)

genre_to_index = {genre: index for index, genre in enumerate(top_genres_by_year_pd['genre'].unique())}
y_genre = [genre_to_index[genre] for genre in top_genres_by_year_pd['genre']]
# 创建3D散点图 - 电影类型
fig_genre = go.Figure(data=[go.Scatter3d(
    x=top_genres_by_year_pd['year'],
    y=y_genre,
    z=top_genres_by_year_pd['count'],
    mode='markers',
    marker=dict(
        size=12,
        color=top_genres_by_year_pd['count'], # 设置颜色为电影数量
        colorscale='Viridis', # 颜色映射样式
        opacity=0.8
    )
)])
fig_genre.update_layout(
    title='每年上映电影数量最多的前三名电影类型',
    scene = dict(
        xaxis_title='年份',
        yaxis_title='电影类型',
        zaxis_title='电影数量'
    ),
    scene_yaxis=dict(tickvals=list(genre_to_index.values()), ticktext=list(genre_to_index.keys()))
)
fig_genre.show()

country_to_index = {country: index for index, country in enumerate(top_countries_by_year_pd['country'].unique())}
y_country = [country_to_index[country] for country in top_countries_by_year_pd['country']]
# 创建3D散点图 - 制片国家/地区
fig_country = go.Figure(data=[go.Scatter3d(
    x=top_countries_by_year_pd['year'],
    y=y_country,
    z=top_countries_by_year_pd['avg_rating'],
    mode='markers',
    marker=dict(
        size=12,
        color=top_countries_by_year_pd['avg_rating'],
        colorscale='Cividis', 
        opacity=0.8
    )
)])
fig_country.update_layout(
    title='每年平均评分前3的制片国家/地区',
    scene = dict(
        xaxis_title='年份',
        yaxis_title='制片国家/地区',
        zaxis_title='平均评分'
    ),
    scene_yaxis=dict(tickvals=list(country_to_index.values()), ticktext=list(country_to_index.keys()))
)
fig_country.show()

# 关闭Spark会话
spark.stop()

运行结果:

注意,本题结果大概率是对的,但是老师有个追加的要求,写代码的时候第二题没有对国家地区进行只选第一个的拆分,所以希望各位自行修改,如果不修改,结果会有一点点差异,而且设计成表格形式比较好,当然也可以直接去掉可视化部分,交差是没问题的了。

第七题

第七题也是按照博客的步骤来进行运行:

注意老师百度网盘的包里面包含了Maven包,请安装到指定位置

然后如果用Linux写Java文件不好写可以再Windows写好后传输到VMware虚拟机中

务必注意文件格式,代码林子雨老师博客已给出

运行结果大概如下

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值