12.4.3 深入挖掘
在数据分析或项目报告中,深入挖掘通常表示进一步深入研究和分析数据,寻找隐藏的信息、模式或趋势。这一步可能包括更复杂的统计分析、机器学习建模、特征工程等,旨在深入了解数据集,为更深层次的理解和决策提供支持。在这一部分,我们将深入挖掘数据,通过更复杂的分析方法来发现一些潜在的关系和模式。主要包括用户评分与动漫类型的相关性和社区互动与动漫热门程度的关系。
(1)下面的代码执行了两个数据集(anime 和 rating)的合并操作,通过它们的共同列 "anime_id" 进行连接,并更改了一些列名,最终生成了一个合并后的数据集 fulldata。
# 合并两个数据集,使用 pd.merge() 方法,通过 "anime_id" 列进行连接
fulldata = pd.merge(anime, rating, on="anime_id", suffixes=[None, "_user"])
# 重命名合并后的数据集的列名
fulldata = fulldata.rename(columns={"rating_user": "user_rating"})
# 输出合并后数据集的形状
print(f"Shape of The Merged Dataset: {fulldata.shape}")
# 输出合并后数据集的前几行,通过样式设置使输出更具可读性
print("\nGlimpse of The Merged Dataset:")
fulldata.head().style.set_properties(**{"background-color": "#2a9d8f", "color": "white", "border": "1.5px solid black"})
对上述代码的具体说明如下所示:
- pd.merge(anime, rating, on="anime_id", suffixes=[None, "_user"]):使用 Pandas 的 merge 方法,通过 "anime_id" 列将两个数据集进行连接,suffixes 参数指定了在列名相同时添加的后缀。
- fulldata.rename(columns={"rating_user": "user_rating"}):用于重命名合并后数据集的列名,将 "rating_user" 列改名为 "user_rating"。
- print(f"Shape of The Merged Dataset: {fulldata.shape}"):输出合并后数据集的形状(行数和列数)。
- fulldata.head().style.set_properties(...):输出合并后数据集的前几行,通过样式设置使输出更具可读性。
运行这段代码后将看到一个带有样式的表格,显示了合并后数据集的形状和前几行内容,如图12-8所示。这有助于检查合并操作是否成功,并初步了解合并后数据集的结构。
图12-8 合并后数据集的形状和前几行内容
(2)使用 Seaborn 库设置了绘图的样式和调色板,这些设置将在后续的 Seaborn 绘图中生效,确保图形有清晰的外观和自定义的颜色。
# 设置绘图样式为 "white"
sns.set_style("white")
# 设置绘图上下文为 "poster",同时调整字体比例
sns.set_context("poster", font_scale=0.7)
# 自定义调色板
palette = ["#1d7874", "#679289", "#f4c095", "#ee2e31", "#ffb563", "#918450", "#f85e00", "#a41623", "#9a031e", "#d6d6d6", "#ffee32", "#ffd100", "#333533", "#202020"]
12.4.4 热门动漫
使用 Seaborn 绘制了一个横向条形图,展示了动漫社区中总会员数最多的前 14 部动漫。其中使用sns.despine(left=True, bottom=True) 移除了可视化图形中的轴线,使图形更清晰。
# 复制合并后的数据集
top_anime = fulldata.copy()
# 根据动漫名称去除重复项,保留第一个出现的项
top_anime.drop_duplicates(subset="name", keep="first", inplace=True)
# 根据会员数降序排序
top_anime_temp1 = top_anime.sort_values(["members"], ascending=False)
# 绘制横向条形图
plt.subplots(figsize=(20, 8))
p = sns.barplot(x=top_anime_temp1["name"][:14], y=top_anime_temp1["members"], palette=palette, saturation=1, edgecolor="#1c1c1c", linewidth=2)
# 设置标题和轴标签
p.axes.set_title("\nTop Anime Community\n", fontsize=25)
plt.ylabel("Total Members", fontsize=20)
plt.xlabel("\nAnime Name", fontsize=20)
# 旋转 x 轴标签
plt.xticks(rotation=90)
# 在条形图上添加标签
for container in p.containers:
p.bar_label(container, label_type="center", padding=6, size=15, color="black", rotation=90,
bbox={"boxstyle": "round", "pad": 0.6, "facecolor": "orange", "edgecolor": "black", "alpha": 1})
# 移除图形中的轴线
sns.despine(left=True, bottom=True)
# 显示图形
plt.show()
执行效果如图12-9所示。
图12-9 动漫社区中总会员数最多的前 14 部动漫
12.4.5 动漫分类
(1)统计并显示动漫的类别(类型),top_anime_temp1["type"].value_counts()用于统计动漫类别(类型)的数量;to_frame().T用于将结果转换为 DataFrame 并进行转置,以便更好地查看;style.set_properties(...)用于通过样式设置,将输出的背景颜色、文字颜色和边框进行调整。
# 统计动漫类别(类型)的数量,并使用样式设置进行输出
top_anime_temp1["type"].value_counts().to_frame().T.style.set_properties(**{"background-color": "#2a9d8f", "color": "white", "border": "1.5px solid black"})
运行这段代码后将看到一个带有样式的表格,显示了不同类型的动漫及其数量,这有助于了解数据集中动漫类别的分布情况。如图12-10所示。
图12-10 不同类型的动漫及其数量
(2)使用 Matplotlib 绘制了一个饼图,展示了动漫的不同类别(类型)的分布情况。
# 设置图形大小
plt.subplots(figsize=(12, 12))
# 不同类别(类型)的标签
labels = "TV", "OVA", "Movie", "Special", "ONA", "Music"
# 饼图的内半径
size = 0.5
# 绘制饼图
wedges, texts, autotexts = plt.pie([len(top_anime_temp1[top_anime_temp1["type"]=="TV"]["type"]),
len(top_anime_temp1[top_anime_temp1["type"]=="OVA"]["type"]),
len(top_anime_temp1[top_anime_temp1["type"]=="Movie"]["type"]),
len(top_anime_temp1[top_anime_temp1["type"]=="Special"]["type"]),
len(top_anime_temp1[top_anime_temp1["type"]=="ONA"]["type"]),
len(top_anime_temp1[top_anime_temp1["type"]=="Music"]["type"])],
explode=(0, 0, 0, 0, 0, 0),
textprops=dict(size=20, color="white"),
autopct="%.2f%%",
pctdistance=0.7,
radius=.9,
colors=palette,
shadow=True,
wedgeprops=dict(width=size, edgecolor="#1c1c1c", linewidth=4),
startangle=0)
# 添加图例
plt.legend(wedges, labels, title="Category", loc="center left", bbox_to_anchor=(1, 0, 0.5, 1))
# 添加标题
plt.title("\nAnime Categories Distribution", fontsize=20)
# 显示图形
plt.show()
在上述代码中,plt.legend(...) 用于添加图例,plt.title(...) 用于添加标题,plt.show() 用于显示图形,这个图形展示了不同动漫类别的分布情况。如图12-11所示。
图12-11 不同动漫类别的分布情况
(3)使用 Seaborn 绘制一个计数图,用于展示不同动漫类别的数量。
# 设置图形大小
plt.subplots(figsize=(20, 8))
# 绘制计数图
p = sns.countplot(x=top_anime_temp1["type"], order=top_anime_temp1["type"].value_counts().index, palette=palette, saturation=1, edgecolor="#1c1c1c", linewidth=3)
# 设置标题和轴标签
p.axes.set_title("\nAnime Categories Hub\n", fontsize=25)
plt.ylabel("Total Anime", fontsize=20)
plt.xlabel("\nAnime Category", fontsize=20)
# 旋转 x 轴标签
plt.xticks(rotation=0)
# 在条形图上添加标签
for container in p.containers:
p.bar_label(container, label_type="center", padding=10, size=25, color="black", rotation=0,
bbox={"boxstyle": "round", "pad": 0.4, "facecolor": "orange", "edgecolor": "black", "linewidth": 3, "alpha": 1})
# 移除图形中的轴线
sns.despine(left=True, bottom=True)
# 显示图形
plt.show()
对上述代码的具体说明如下所示:
- sns.countplot(...):使用 Seaborn 绘制计数图,展示了不同动漫类别的数量。
- order=top_anime_temp1["type"].value_counts().index:用于按照类别数量的降序排列条形。
- p.bar_label(...):用于在条形图上添加标签。
- sns.despine(left=True, bottom=True) :用于移除图形中的轴线,使图形更清晰。
- plt.show():用于显示可视化图形,这个图形展示了不同动漫类别的数量分布情况。如图12-12所示。
图12-12 不同动漫类别的数量分布情况
我们可以得出如下结论:
- 有3402部动漫在电视上播出,占总动漫数量的30.48%。
- 有2111部动漫作为电影上映,占总动漫数量的18.91%。
- 有3090部动漫作为OVA(Original Video Animation)播出,占总动漫数量的27.69%,这也超过了作为ONA(Original Net Animation)播出的526部动漫,占总动漫数量的4.71%。