通过python对excel进行数据分析和可视化

cpp 复制代码
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

file_path = "C:\\Users\\86138\\Desktop\\book_list-计算机-机器学习-linux-android-数据库-互联网.xlsx"
data = pd.read_excel(file_path)

need_data = data[['书名', '评分', '评价人数']].copy()

#为 data_cleaned 数据框添加一个新列 书名字数,使用.str.len() 算字符串长度
need_data['书名字数'] = need_data['书名'].str.len()

#删除 data_cleaned 数据框中包含缺失值的行,使用 .dropna() 方法
need_data = need_data.dropna()
# 将评分列转换为数值类型,处理错误值
need_data['评分'] = pd.to_numeric(need_data['评分'], errors='coerce')
# 将评价人数列转换为数值类型,处理错误值
need_data['评价人数'] = pd.to_numeric(need_data['评价人数'], errors='coerce')
# 再次删除包含缺失值或无效值的行
need_data = need_data.dropna()

# sns.set() 函数设置绘图风格为 whitegrid(白色网格),调色板为 pastel(柔和色调),字体缩放比例为 1.2。
# 使用 plt.figure(figsize=(9, 7)) 创建一个大小为 (9, 7) 的图形,用于容纳后续的子图。
sns.set(style="whitegrid", palette="pastel", font_scale=1.2)
plt.figure(figsize=(9, 7))

# 创建第一个子图:
# plt.subplot(3, 1, 1) 创建一个 3 行 1 列的子图,并将子图设为第一个。
# 使用 sns.histplot() 绘制 评价人数 的直方图,bins=20 将数据划分为 20 个直方图区间,kde=True 添加核密度估计曲线
# 使用 plt.title() 为子图设标题,plt.xlabel() 和 plt.ylabel() 设置 x 轴和 y 轴的标签。
# 发现:评论计数的分布:大多数书籍的评论数量相对较少,但少数书籍的评论数量非常高
plt.subplot(3, 1, 1)
sns.histplot(need_data['评价人数'], bins=20, kde=True, color='skyblue')
plt.title('Rating with book counts')
plt.xlabel('Rating')
plt.ylabel('Book')

# 创建第二个子图
# 书名长度的分布:书名通常在5到15个字符之间,还有一些较长的字符
plt.subplot(3, 1, 2)
sns.histplot(need_data['书名字数'], bins=15, kde=True, color='lightgreen')
plt.title('Distribution of Book Title Lengths')
plt.xlabel('Number of Characters in Title')
plt.ylabel('Frequency')

# 第三个子图
# 评级分布:评级通常聚集在较高的范围内,介于8到10之间。
plt.subplot(3, 1, 3)
sns.histplot(need_data['评分'], bins=10, kde=True, color='salmon')
plt.title('Distribution of Ratings')
plt.xlabel('Ratings')
plt.ylabel('Frequency')

# 调整子图布局,使它们紧凑排列,避免重叠。
# 使用 plt.show() 显示绘制的图形
plt.tight_layout()
plt.show()

# 打印出 data 数据框的前几行,以便查看数据集的结构,使用 .head() 方法。
print("数据的前几行:")
print(data.head())

# 创建一个新的图形,大小为 15x10,用于绘制饼图和折线图
plt.figure(figsize=(15, 10))

# 将 评分 列的数据分成不同的分组(bins),范围是 0-6、6-7、7-8、8-9、9-10,使用 pd.cut() 函数,并为每个分组分配标签。
# 使用 value_counts(sort=False) 统计每个分组的数量。
rating_bins = pd.cut(need_data['评分'], bins=[0, 7,8, 9, 10], labels=['0 - 7','7 - 8', '8 - 9', '9 - 10'])
rating_counts = rating_bins.value_counts(sort=False)

# 创建一个 2 行 1 列的子图布局,并将当前子图设置为第一个。
# 使用 rating_counts.plot.pie() 绘制饼图,autopct='%1.1f%%' 表示在饼图上显示百分比,colors=sns.color_palette('pastel') 使用柔和色调,startangle=140 表示起始角度。
# 设置饼图的标题,并将 y 轴标签设为空,以提高美观度
plt.subplot(2, 1, 1)
rating_counts.plot.pie(autopct='%1.1f%%', colors=sns.color_palette('pastel'), startangle=140)
plt.title('Rating Counts')
plt.ylabel('')


plt.subplot(2, 1, 2)
sorted_data = need_data.sort_values(by='评分')
plt.plot(sorted_data['评分'], sorted_data['评价人数'], marker='o', color='teal', label='Review Counts')
plt.title('Single book review counts')
plt.xlabel('Book counts')
plt.ylabel('Reviewer counts')
plt.grid(alpha=0.3)
plt.legend()

# Adjust layout and show plots
plt.tight_layout()
plt.show()


#按 评分 列对 data_cleaned 数据框进行分组,使用 groupby('评分'),并计算每个组中 评价人数 的总和,结果存储在 total_reviews_by_rating 中。
total_reviews_by_rating = need_data.groupby('评分')['评价人数'].sum()

# Plot the total review counts across ratings
plt.figure(figsize=(10, 6))
plt.plot(total_reviews_by_rating.index, total_reviews_by_rating.values, marker='o', color='teal', label='Total Reviews')
plt.title('Sum count of reviewers', fontsize=16)
plt.xlabel('Book rating', fontsize=12)
plt.ylabel('Reviewer counts', fontsize=12)
plt.grid(alpha=0.3)
plt.legend()
plt.tight_layout()
plt.show()

整理后的代码

cpp 复制代码
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns


def load_and_preprocess_data(file_path):
    """
    加载并预处理数据
    :param file_path: Excel文件的路径
    :return: 预处理后的数据
    """
    data = pd.read_excel(file_path)
    # 提取所需数据列
    need_data = data[['书名', '评分', '评价人数']].copy()
    # 计算书名字数
    need_data['书名字数'] = need_data['书名'].str.len()
    # 去除缺失值和处理数据类型
    need_data = need_data.dropna(subset=['书名', '评分', '评价人数'])
    need_data['评分'] = pd.to_numeric(need_data['评分'], errors='coerce')
    need_data['评价人数'] = pd.to_numeric(need_data['评价人数'], errors='coerce')
    need_data = need_data.dropna(subset=['评分', '评价人数'])
    return need_data


def plot_histograms(need_data):
    """
    绘制直方图和核密度估计图
    :param need_data: 预处理后的数据
    """
    sns.set(style="whitegrid", palette="pastel", font_scale=1.2)
    fig, axs = plt.subplots(3, 1, figsize=(9, 7))
    # 评价人数的分布
    sns.histplot(need_data['评价人数'], bins=20, kde=True, color='skyblue', ax=axs[0])
    axs[0].set_title('Distribution of Review Counts')
    axs[0].set_xlabel('Review Counts')
    axs[0].set_ylabel('Frequency')
    # 书名字数的分布
    sns.histplot(need_data['书名字数'], bins=15, kde=True, color='lightgreen', ax=axs[1])
    axs[1].set_title('Distribution of Book Title Lengths')
    axs[1].set_xlabel('Number of Characters in Title')
    axs[1].set_ylabel('Frequency')
    # 评分的分布
    sns.histplot(need_data['评分'], bins=10, kde=True, color='salmon', ax=axs[2])
    axs[2].set_title('Distribution of Ratings')
    axs[2].set_xlabel('Ratings')
    axs[2].set_ylabel('Frequency')
    plt.tight_layout()
    plt.show()


def plot_pie_and_line_charts(need_data):
    """
    绘制饼图和折线图
    :param need_data: 预处理后的数据
    """
    plt.figure(figsize=(15, 20))
    # 分组统计评分分布
    rating_bins = pd.cut(need_data['评分'], bins=[0, 7, 8, 9, 10], labels=['0 - 7', '7 - 8', '8 - 9', '9 - 10'])
    rating_counts = rating_bins.value_counts(sort=False)
    # 饼图
    ax1 = plt.subplot(2, 1, 1)
    rating_counts.plot.pie(autopct='%1.1f%%', colors=sns.color_palette('pastel'), startangle=140)
    ax1.set_title('Rating Counts')
    ax1.set_ylabel('')
    # 折线图
    ax2 = plt.subplot(2, 1, 2)
    sorted_data = need_data.sort_values(by='评分')
    ax2.plot(sorted_data['评分'], sorted_data['评价人数'], marker='o', color='teal', label='Review Counts')
    ax2.set_title('Single book review counts')
    ax2.set_xlabel('Book counts')
    ax2.set_ylabel('Reviewer counts')
    ax2.grid(alpha=0.3)
    ax2.legend()
    plt.tight_layout()
    plt.show()


def plot_total_review_counts(need_data):
    """
    绘制总评论人数与评分的关系图
    :param need_data: 预处理后的数据
    """
    total_reviews_by_rating = need_data.groupby('评分')['评价人数'].sum()
    plt.figure(figsize=(10, 6))
    plt.plot(total_reviews_by_rating.index, total_reviews_by_rating.values, marker='o', color='teal', label='Total Reviews')
    plt.title('Sum count of reviewers', fontsize=16)
    plt.xlabel('Book rating', fontsize=12)
    plt.ylabel('Reviewer counts', fontsize=12)
    plt.grid(alpha=0.3)
    plt.legend()
    plt.tight_layout()
    plt.show()


if __name__ == "__main__":
    file_path = "C:\\Users\\86138\\Desktop\\book_list-计算机-机器学习-linux-android-数据库-互联网.xlsx"
    need_data = load_and_preprocess_data(file_path)
    print("数据的前几行:")
    print(need_data.head())
    plot_histograms(need_data)
    plot_pie_and_line_charts(need_data)
    plot_total_review_counts(need_data)
  1. 第一个子图( plt.subplot(3, 1, 1) ):
    • 图像类型:直方图和核密度估计图( sns.histplot )。
    • 分析关系:
      • 该图展示了 评价人数 的分布情况。
      • 横轴表示 评价人数,纵轴表示 频率。
      • 通过将 评价人数 数据划分为 20 bins 并绘制直方图,再加上核密度估计曲线,可以观察到书籍的评价人数的分布趋势。
      • 发现:可以看到大多数书籍的评价人数相对较少,但有少数书籍的评价人数非常高,呈现长尾分布,这意味着少数热门书籍吸引了大量的评价,而大部分书籍的评价相对较少。
  2. 第二个子图( plt.subplot(3, 1, 2) ):
    • 图像类型:直方图和核密度估计图( sns.histplot )。
    • 分析关系:
      • 该图展示了 书名字数 的分布情况。
      • 横轴表示 书名字数,即书名的字符长度,纵轴表示 频率。
      • 划分了 15 bins 并绘制直方图和核密度估计曲线。
      • 从图中可以观察到书名长度的分布规律,通常在 5 15 个字符之间,但也存在一些较长书名的书籍,能让用户了解书籍命名时书名长度的大致范围和分布情况。
  3. 第三个子图( plt.subplot(3, 1, 3) ):
    • 图像类型:直方图和核密度估计图( sns.histplot )。
    • 分析关系:
      • 该图展示了 评分 的分布情况。
      • 横轴表示 评分,纵轴表示 频率。
      • 划分了 10 bins 并绘制直方图和核密度估计曲线。
      • 可以看出书籍的 评分 通常聚集在较高的范围内,一般介于 8 10 之间,能让用户了解书籍评分的整体分布趋势,了解用户对书籍的总体评价倾向。

第二个 plt.figure 中的两个子图:

  1. 第一个子图( plt.subplot(2, 1, 1) ):
    • 图像类型:饼图( rating_counts.plot.pie )。
    • 分析关系:
      • 首先使用 pd.cut 评分 分成不同的范围: 0-6 6-7 7-8 8-9 9-10 ,并为这些范围分配了相应的标签。
      • 该饼图展示了不同评分范围的书籍在整个数据集中所占的比例。
      • 可以直观地看出不同评分范围的书籍的相对占比,使用 autopct='%1.1f%%' 显示每个扇形部分的百分比,帮助用户快速了解评分的分布结构。
  2. 第二个子图
    • 图像类型:折线图( plt.plot )。
    • 分析关系:
      • 首先对 data_cleaned 评分 进行排序( data_cleaned.sort_values(by=' 评分 ') )。
      • 该图展示了 评价人数 评分 的关系。
      • 横轴是 评分,纵轴是 评价人数,使用 marker='o' 标记每个数据点。
      • 可以看出不同评分的书籍对应的评价人数的趋势,可能反映出评分高低与评价人数多少之间的关系,例如评分高的书籍是否更受关注,评价人数更多。

第三个 plt.figure

  • 图像类型:折线图( plt.plot )。
  • 分析关系:
    • 首先对 data_cleaned 评分 分组并计算每个组中 评价人数 的总和( data_cleaned.groupby(' 评分 ')[' 评价人数 '].sum() )。
    • 该图展示了不同评分下的总评价人数的关系。
    • 横轴是 Book rating ,纵轴是 Reviewer counts
    • 可以看出不同评分的书籍的总评价人数,例如可以发现哪个评分范围的书籍吸引了最多的总评价,帮助用户分析不同评分对评价人数总和的影响,以及不同评分书籍的受欢迎程度(从评价人数总和的角度)。
相关推荐
PieroPc1 分钟前
使用 Axios、原生 JavaScript 和 Django 5 的搭建一个简单前后端博客系统
后端·python·django
蹦蹦跳跳真可爱5896 分钟前
Python----Python爬虫(selenium的使用,处理弹窗,拖拽元素,调用js方法,等待元素,参数使用)
爬虫·python·selenium
一棵树长得超出它自己6 分钟前
selenium合集
开发语言·python·selenium
_可乐无糖29 分钟前
如何从串 ‘ 中国 +86‘ 中,获取到‘中国’:strip()、split()及正则表达式的使用
python
金色旭光1 小时前
docker-compose部署下Fastapi中使用sqlalchemy和Alembic
python
Spcarrydoinb2 小时前
python学习笔记—15—数据容器之列表
笔记·python·学习
Want5953 小时前
《Python趣味编程》专栏介绍与专栏目录
开发语言·python
qq19783663083 小时前
Python 批量生成Word 合同
开发语言·python·自动化·word
io_T_T3 小时前
python SQLAlchemy ORM——从零开始学习 02简单的增删查改
python
Q_19284999063 小时前
基于Django的农业管理系统
后端·python·django