背景介绍
在碎片化阅读时代,我们常常难以直观感知自己的阅读习惯——每月读了多久?哪本书最常读?阅读时间是否有规律?为了解决这些问题,我开发了一个本地阅读时长统计工具,通过CSV存储数据、Pandas分析、Matplotlib可视化,帮助用户轻松跟踪阅读趋势。工具无需外部服务,完全本地运行,适合数据分析初学者练习核心技能。
思路分析
工具分为四个核心模块,每个模块职责明确:
1. 数据存储:用CSV文件保存阅读记录(日期、书籍、时长),结构简单易维护。
2. 记录管理:实现添加记录和初始化CSV的功能,确保数据格式规范。
3. 统计分析:利用Pandas的时间筛选、分组聚合,计算总时长、平均时长和最常阅读书籍。
4. 可视化:通过Matplotlib生成柱状图(每日时长)和折线图(每月趋势),直观展示数据。
5. 交互逻辑:命令行菜单引导用户操作,降低使用门槛。
代码实现
1. 环境准备
首先安装依赖库:
pip install pandas matplotlib
2. 完整代码
import pandas as pd
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import os
# -------------------------- 数据初始化与存储 --------------------------
def init_csv():
"""初始化CSV文件(若不存在则创建带表头的空文件)"""
if not os.path.exists('reading_records.csv'):
df = pd.DataFrame(columns=['date', 'book', 'duration'])
df.to_csv('reading_records.csv', index=False)
print("✅ 初始化成功:创建reading_records.csv")
def add_reading_record(date_str, book_name, duration):
"""添加阅读记录到CSV文件"""
try:
# 验证日期格式
datetime.strptime(date_str, '%Y-%m-%d')
# 验证时长为正整数
if duration <= 0:
raise ValueError("时长必须大于0")
# 构造新记录
new_record = pd.DataFrame([[date_str, book_name, duration]],
columns=['date', 'book', 'duration'])
# 追加到CSV(不写索引和表头)
new_record.to_csv('reading_records.csv', mode='a', header=False, index=False)
print("✅ 记录保存成功!")
except ValueError as e:
print(f"❌ 输入错误:{e}")
except Exception as e:
print(f"❌ 保存失败:{str(e)}")
# -------------------------- 统计分析模块 --------------------------
def analyze_reading_data(time_range_days):
"""分析指定时间范围内的阅读数据(总时长、平均、最常读书籍)"""
try:
# 读取CSV并解析日期列
df = pd.read_csv('reading_records.csv', parse_dates=['date'])
if df.empty:
return None
# 筛选时间范围
end_date = datetime.now()
start_date = end_date - timedelta(days=time_range_days)
filtered_df = df[df['date'] >= start_date]
if filtered_df.empty:
return None
# 计算统计指标
total_duration = filtered_df['duration'].sum()
avg_duration = total_duration / time_range_days
# 最常阅读书籍(按总时长排序)
book_stats = filtered_df.groupby('book')['duration'].sum().sort_values(ascending=False)
top_book = book_stats.index[0]
top_book_duration = book_stats.iloc[0]
return {
'total': total_duration,
'avg': round(avg_duration, 2),
'top_book': top_book,
'top_book_duration': top_book_duration
}
except Exception as e:
print(f"❌ 分析失败:{str(e)}")
return None
# -------------------------- 可视化模块 --------------------------
def plot_daily_bar():
"""生成最近14天每日阅读时长柱状图"""
try:
df = pd.read_csv('reading_records.csv', parse_dates=['date'])
if df.empty:
print("❌ 无数据可可视化")
return
# 筛选最近14天数据
start_date = datetime.now() - timedelta(days=14)
daily_data = df[df['date'] >= start_date].groupby('date')['duration'].sum().reset_index()
if daily_data.empty:
print("❌ 最近14天无阅读记录")
return
# 绘制柱状图
plt.figure(figsize=(10,5))
plt.bar(daily_data['date'].dt.strftime('%Y-%m-%d'), daily_data['duration'], color='#3498db')
plt.title('最近14天每日阅读时长', fontsize=14)
plt.xlabel('日期', fontsize=12)
plt.ylabel('时长(分钟)', fontsize=12)
plt.xticks(rotation=45)
plt.tight_layout() # 自动调整布局避免重叠
plt.savefig('daily_bar.png', dpi=100)
print("✅ 柱状图保存:daily_bar.png")
except Exception as e:
print(f"❌ 绘图失败:{str(e)}")
def plot_monthly_line():
"""生成最近3个月每月阅读时长折线图"""
try:
df = pd.read_csv('reading_records.csv', parse_dates=['date'])
if df.empty:
print("❌ 无数据可可视化")
return
# 筛选最近3个月数据
start_date = datetime.now() - timedelta(days=90)
monthly_data = df[df['date'] >= start_date].copy()
# 按月份分组(格式:YYYY-MM)
monthly_data['month'] = monthly_data['date'].dt.strftime('%Y-%m')
monthly_total = monthly_data.groupby('month')['duration'].sum().reset_index()
if monthly_total.empty:
print("❌ 最近3个月无阅读记录")
return
# 绘制折线图
plt.figure(figsize=(10,5))
plt.plot(monthly_total['month'], monthly_total['duration'], marker='o', color='#e74c3c', linewidth=2)
plt.title('最近3个月阅读时长趋势', fontsize=14)
plt.xlabel('月份', fontsize=12)
plt.ylabel('总时长(分钟)', fontsize=12)
plt.grid(alpha=0.3) # 添加网格线
plt.tight_layout()
plt.savefig('monthly_line.png', dpi=100)
print("✅ 折线图保存:monthly_line.png")
except Exception as e:
print(f"❌ 绘图失败:{str(e)}")
# -------------------------- 主交互逻辑 --------------------------
def main():
init_csv() # 启动时初始化CSV
while True:
print("\n=== 阅读时长统计工具 ===")
print("1. 添加阅读记录")
print("2. 查看统计报告(最近7/30天)")
print("3. 生成可视化图表")
print("4. 退出")
choice = input("请输入操作编号:")
if choice == '1':
date = input("日期(YYYY-MM-DD):")
book = input("书籍名称:")
try:
duration = int(input("阅读时长(分钟):"))
add_reading_record(date, book, duration)
except ValueError:
print("❌ 时长必须是整数!")
elif choice == '2':
range_choice = input("统计范围:1.最近7天 2.最近30天:")
days = 7 if range_choice == '1' else 30 if range_choice == '2' else None
if days:
stats = analyze_reading_data(days)
if stats:
print(f"\n--- 最近{days}天统计 ---")
print(f"总时长:{stats['total']}分钟")
print(f"平均每日:{stats['avg']}分钟")
print(f"最常阅读:《{stats['top_book']}》({stats['top_book_duration']}分钟)")
else:
print(f"❌ 最近{days}天无有效记录")
elif choice == '3':
plot_daily_bar()
plot_monthly_line()
elif choice == '4':
print("再见!")
break
else:
print("❌ 无效操作,请重新输入!")
if __name__ == "__main__":
main()
功能演示
运行代码后,通过命令行交互:
1. 添加记录:输入日期、书籍、时长,自动保存到CSV。
2. 统计报告:选择时间范围,查看总时长、平均时长和最常读书籍。
3. 可视化:生成两张图表,分别保存为daily_bar.png和monthly_line.png。
总结
这个工具覆盖了数据分析的核心流程:数据收集→存储→分析→可视化。通过实践,我巩固了以下技能:
– CSV文件的读写与初始化。
– Pandas的时间筛选、分组聚合(groupby)。
– Matplotlib的图表定制(标题、标签、布局)。
– 命令行交互的错误处理与用户引导。
扩展方向:
– 支持多用户(添加user列)。
– 导出PDF报告(结合ReportLab)。
– 添加周度统计(比如每周哪一天阅读最多)。
如果你也想跟踪阅读习惯,不妨试试这个工具——它不仅能帮你优化阅读,还能提升数据分析能力!