背景介绍
在信息爆炸的时代,阅读是自我提升的重要途径。但如何量化阅读行为、发现潜在的阅读习惯?本文将带你开发一个个人书籍阅读统计分析工具,通过解析本地阅读记录(CSV/JSON格式),自动生成统计报告和可视化图表,帮助你直观掌握阅读规律,优化阅读计划。
技术思路分析
工具的核心流程分为四步:
1. 文件读取:解析CSV/JSON格式的阅读记录,提取结构化数据。
2. 数据处理:解析日期、分组统计(月度书籍数、类型时长占比等)。
3. 可视化:使用Matplotlib绘制柱状图、饼图、折线图,直观展示数据。
4. 结果输出:保存统计文本和图表文件,方便用户查看。
代码实现:从数据到可视化的完整流程
以下是完整的Python实现(依赖pandas和matplotlib,需提前安装:pip install pandas matplotlib):
1. 导入依赖库
import pandas as pd
import matplotlib.pyplot as plt
import os
2. 文件读取与数据解析
使用pandas读取CSV文件,并解析日期格式:
def read_csv_file(file_path):
"""读取CSV格式的阅读记录文件,解析日期列"""
try:
df = pd.read_csv(file_path)
# 将日期列转换为datetime类型
df['阅读开始日期'] = pd.to_datetime(df['阅读开始日期'])
df['阅读结束日期'] = pd.to_datetime(df['阅读结束日期'])
return df
except FileNotFoundError:
print(f"错误:文件 {file_path} 不存在!")
return None
3. 统计分析模块
月度书籍数量统计
def analyze_monthly_books(df):
"""统计每月阅读的书籍数量(按阅读结束日期分组)"""
monthly_counts = df.groupby(df['阅读结束日期'].dt.month)['书名'].count()
return monthly_counts
类型阅读时长统计
def analyze_type_duration(df):
"""统计各类型书籍的阅读时长总和"""
type_duration = df.groupby('类型')['阅读时长(小时)'].sum()
return type_duration
4. 可视化模块
月度阅读量柱状图
def plot_monthly_books(monthly_counts, output_path):
"""绘制月度阅读量柱状图"""
plt.figure(figsize=(8, 6))
monthly_counts.plot(kind='bar', color='skyblue', zorder=3)
plt.title('月度阅读书籍数量')
plt.xlabel('月份')
plt.ylabel('书籍数量')
plt.xticks(rotation=0)
# 美化图表(隐藏多余边框、添加网格线)
ax = plt.gca()
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.grid(axis='y', zorder=0)
plt.tight_layout()
plt.savefig(output_path)
plt.close()
类型占比饼图(按时长)
def plot_type_pie(type_duration, output_path):
"""绘制书籍类型阅读时长占比饼图"""
plt.figure(figsize=(8, 6))
labels = type_duration.index
sizes = type_duration.values
# 自定义百分比标签(显示百分比和时长)
autopct = lambda p: f'{p:.2f}%\n({sum(sizes)*p/100:.0f}小时)'
plt.pie(sizes, labels=labels, autopct=autopct, startangle=90,
textprops={'fontsize': 10}, colors=['#ff9999', '#66b3ff', '#99ff99', '#ffcc99'])
plt.axis('equal') # 保证饼图为正圆形
plt.title('书籍类型阅读时长占比')
plt.tight_layout()
plt.savefig(output_path)
plt.close()
阅读时长趋势折线图
def plot_duration_trend(df, output_path):
"""绘制阅读时长随时间变化的折线图"""
# 按阅读结束日期排序
df_sorted = df.sort_values('阅读结束日期')
plt.figure(figsize=(10, 6))
plt.plot(df_sorted['阅读结束日期'], df_sorted['阅读时长(小时)'],
marker='o', linestyle='-', color='orange', zorder=3)
plt.title('阅读时长随时间变化趋势')
plt.xlabel('阅读结束日期')
plt.ylabel('阅读时长(小时)')
plt.xticks(rotation=45, ha='right')
# 美化图表
ax = plt.gca()
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.grid(axis='y', zorder=0)
plt.tight_layout()
plt.savefig(output_path)
plt.close()
5. 统计文本生成
def generate_stats_text(monthly_counts, type_duration, df):
"""生成统计结果的文本报告"""
total_duration = type_duration.sum()
total_books = len(df)
text = "### 月度阅读量\n"
for month, count in monthly_counts.items():
text += f"- {month}月:{count} 本\n"
text += "\n### 类型占比(按时长)\n"
for typ in type_duration.index:
books_count = (df['类型'] == typ).sum() # 该类型的书籍数量
duration = type_duration[typ]
ratio = (duration / total_duration) * 100
text += f"- {typ}:{books_count} 本,{duration} 小时,占比 {ratio:.2f}%\n"
text += f"\n### 总阅读统计\n"
text += f"- 总阅读时长:{total_duration} 小时\n"
text += f"- 平均每本书阅读时长:{total_duration / total_books:.2f} 小时\n"
return text
6. 主函数:整合流程
def main():
# 输入输出路径设置
input_file = 'reading_records.csv'
output_dir = 'output'
os.makedirs(output_dir, exist_ok=True) # 确保输出目录存在
# 读取文件
df = read_csv_file(input_file)
if df is None:
return
# 统计分析
monthly_counts = analyze_monthly_books(df)
type_duration = analyze_type_duration(df)
# 生成统计文本并保存
stats_text = generate_stats_text(monthly_counts, type_duration, df)
with open(os.path.join(output_dir, 'stats.txt'), 'w', encoding='utf-8') as f:
f.write(stats_text)
print("统计文本已保存到 output/stats.txt")
# 生成可视化图表
plot_monthly_books(monthly_counts, os.path.join(output_dir, 'monthly_books.png'))
plot_type_pie(type_duration, os.path.join(output_dir, 'type_pie.png'))
plot_duration_trend(df, os.path.join(output_dir, 'duration_trend.png'))
print("可视化图表已保存到 output 目录!")
if __name__ == "__main__":
# 解决Matplotlib中文显示问题
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
main()
运行与测试
- 准备CSV文件(格式参考问题描述),命名为
reading_records.csv。 - 运行代码:
python 脚本名.py。 - 查看
output目录,将生成stats.txt、monthly_books.png、type_pie.png、duration_trend.png。
总结与扩展
通过这个项目,你将掌握:
– 文件处理:解析CSV/JSON格式的结构化数据。
– 数据统计:日期解析、分组聚合(pandas的groupby操作)。
– 可视化:Matplotlib的图表绘制与美化(字体、布局、样式)。
扩展方向:
– 支持JSON格式的阅读记录。
– 增加“阅读速度”(字数/小时)、“书籍评分”等统计维度。
– 结合Streamlit实现交互式Web可视化。
通过代码,我们将冰冷的阅读记录转化为直观的图表和报告,让阅读习惯“可视化”。现在,开始分析你的阅读数据,优化阅读计划吧!