ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于Python的图书馆借阅数据分析:从数据清洗到可视化实战

基于Python的图书馆借阅数据分析:从数据清洗到可视化实战 简介《基于Python的图书馆借阅数据分析设计与实现》是一份专科和本科毕业论文资源面向计算机、信息管理及相关专业毕业生旨在帮助完成图书馆数据类课题。课题以图书馆借阅数据为对象完整覆盖数据爬取、清洗、存储、统计建模与可视化展示等环节同时结合Django框架搭建可交互的借阅分析系统帮助理解从原始数据到业务分析结果的全过程。论文结构完整涵盖摘要、关键词、绪论、国内外研究现状、相关技术与工具、数据获取与处理、数据分析方法等章节详细介绍了Pandas、Numpy、Matplotlib、Scikit-learn等主流数据分析库在数据清洗、特征工程、模型建立中的应用并对数据可视化与统计挖掘方法给出了可操作示例可直接迁移至同类课题。资源包仅包含1个DOCX文件大小约35KB全文已做降重处理字数超过一万内容组织清晰既可作为毕业设计的框架参考也能支撑论文写作、系统设计与功能模块的改编复用。目前该资源已有473人浏览学习适合需要快速搭建论文体系、借鉴数据采集与分析方法或想结合Python与网络爬虫、Django进行综合开发的读者使用。1. 基于python的图书馆借阅数据分析到底在解决什么问题图书馆借阅系统每天产生少则几百、多则上万条借还流水常见的管理做法是让管理员在excel里做透视表统计每月借了多少册、哪些书最热门。这种模式只能回答“发生了什么”回答不了“为什么会发生”和“接下来会怎样”。基于python的图书馆借阅数据分析正是把散落在借阅流水、读者表、图书表里的数据汇成一张可分析的宽表然后用可复现的脚本完成时间序列分析、读者分层建模和可视化报表输出。它解决的是三个具体问题第一借阅数据格式混乱怎么清洗第二借阅行为用什么指标量化第三分析结果如何变成管理员能直接看的图形和表格。这套方法既能在毕业设计项目中作为完整实现样例也能用于图书馆或资料室的日常数据运营。本文所有代码都围绕最标准的借阅流水格式展开在jupyter notebook中逐段执行或者在pycharm里按脚本运行不需要额外安装数据库组件只依赖pandas和几个常用库。2. 借阅数据清洗与合并从流水明细到分析宽表借阅数据很少是“开箱即用”的。真实的借阅系统导出的excel通常包含多张表且字段命名不统一、时间格式混乱、证号有前导零丢失问题。正式开始分析前必须先完成字段确认、脏数据清理和表间合并。这一步做不好后面的所有指标都会失真。2.1 借阅流水表的字段结构与常见脏数据最常见的借阅相关表有三张借阅流水表、读者信息表、图书信息表。我一般会先按下列字段清单核对原始数据表名常见字段说明借阅流水表借阅证号、图书条码、借书时间、还书时间、续借次数每条记录代表一次借阅行为读者信息表借阅证号、读者类型、学院/部门、年级/职称读者属性用于分组分析图书信息表图书条码、书名、中图分类号、馆藏地点、出版年图书属性用于分类挖掘三张表通过借阅证号和图书条码关联。最容易踩的坑是借阅证号在原始数据里被excel识别成数字前导零被吃掉导致merge时匹配失败借书时间和还书时间可能是字符串格式从2023/01/05到2023-01-05 10:23:45都有。还书时间为空通常代表书还没还这个空值在处理时不能直接删除而是要单独标记成“在借”。此外系统在办理续借时可能生成两条一模一样的记录去重必须放在所有统计之前。2.2 用pandas统一时间格式并进行去重拿到三张表的原始excel后第一步是统一读取方式。下面这段代码用于读入借阅流水并完成基础清理import pandas as pd # 读取借阅流水借书时间和还书时间直接按日期时间列解析 df_borrow pd.read_excel( borrow.xlsx, parse_dates[借书时间, 还书时间], # 自动识别多种时间格式 dtype{借阅证号: str} # 证号必须按字符串读入防止前导零丢失 ) # 去除完全重复的记录 df_borrow df_borrow.drop_duplicates() # 借书时间为空的记录无效直接删除 df_borrow df_borrow.dropna(subset[借书时间]) # 还书时间为空表示在借标记为当前时间后续计算借阅天数时使用 df_borrow.loc[df_borrow[还书时间].isna(), 还书时间] pd.Timestamp.now()parse_dates参数告诉pandas哪些列需要按照时间类型解析这样后续可以直接做日期加减不需要再手动pd.to_datetime。dtype参数保证借阅证号以字符串形式读出避免“000123”变成“123”。drop_duplicates()默认判断整行是否完全一致对于续借场景下只有操作时间不同的记录不会误删。最后一步把空还书时间替换为当前时间是为了让借阅天数变成正数但这只在“分析时点”有效如果数据会更新建议额外保留一个“是否在借”标记列。2.3 用merge把借阅、读者、图书三张表拼成宽表单张流水表只能算借阅次数想要按读者类型、图书分类分析必须把三张表合并成宽表。常见做法是用pandas的merge函数键分别取借阅证号和图书条码# 读取读者表和图书表同样用string类型读取编码字段 df_reader pd.read_excel(reader.xlsx, dtype{借阅证号: str}) df_book pd.read_excel(book.xlsx, dtype{图书条码: str}) # 先合并读者信息再合并图书信息 df df_borrow.merge(df_reader, on借阅证号, howleft) df df.merge(df_book, on图书条码, howleft) # 检查合并后数据是否完整 print(df.shape) print(df[[读者类型, 书名, 中图分类号]].isna().sum())merge的on参数指定关联键howleft表示以借阅流水表为主体左边表的每条记录都保留右边表匹配不到的部分填充为NaN。合并完成后输出缺失值数量如果“读者类型”缺失很多说明借阅证号在两张表里格式不一致最容易被忽略的就是证号前后的空格。这时可以用df[借阅证号] df[借阅证号].str.strip()统一去除。合并后的宽表每一行仍是一次借阅行为但已经带上了读者和图书属性后续分析不必反复查表。3. 借阅行为分析核心指标计算与读者分层宽表准备好之后下一步就是把“借阅记录”变成“行为指标”。图书馆借阅数据分析的核心不是看单条记录而是看读者和图书在时间轴上的规律。我通常会从三个维度切入借阅时长与周期、读者类型分组画像、热门图书与学科分布。3.1 借阅时长、借阅周期和续借率先算一组基础指标一次借阅行为的质量不只体现在借了没有还体现在借了多久、有没有续借。代码里可以直接用时间列做差# 计算单次借阅天数 df[借阅天数] (df[还书时间] - df[借书时间]).dt.days # 出现负数说明还书时间早于借书时间通常是录入错误置为缺失值 df.loc[df[借阅天数] 0, 借阅天数] None # 统计每位读者的借阅总次数、平均借阅天数、续借次数列 borrow_stats df.groupby(借阅证号).agg( 借阅次数(借书时间, count), 平均借阅天数(借阅天数, mean), 续借次数(续借次数, sum) ) # 续借率续借总次数 / 借阅总次数反映读者对图书的依赖程度 borrow_stats[续借率] borrow_stats[续借次数] / borrow_stats[借阅次数]这里用groupby().agg()一次算出多个聚合指标列名直接作为Python标识符传入可读性比agg({列名: sum})更好。借阅天数取平均值前要留意空值NaN不会参与计算但如果某条记录借阅天数为0当天借当天还也会拉低均值。续借率数值通常在0到1之间如果发现大于1多半是因为同一本书被多次续借而次数统计口径不一致需检查“续借次数”列单位。3.2 按读者类型和学院分组的借阅画像单个读者的指标波动大按读者类型聚合后才能看出规律。例如研究生和本科生的借阅习惯、热门学院的平均借阅量差异。代码如下# 按借阅月份和读者类型生成交叉统计 df[借阅月份] df[借书时间].dt.to_period(M) reader_month df.groupby([读者类型, 借阅月份]).size().unstack(fill_value0) # 按学院统计人均借阅量 college_stats df.groupby(所属学院).agg( 读者数(借阅证号, nunique), 借阅总量(借书时间, count) ) college_stats[人均借阅量] college_stats[借阅总量] / college_stats[读者数] # 取借阅总量最高的前10个学院 print(college_stats.sort_values(借阅总量, ascendingFalse).head(10))dt.to_period(M)把时间转换为年月周期这样按月份分组不会受到“天”的干扰。unstack()把读者类型从行索引变成列名形成一张行是月份、列是读者类型的交叉表适合后续绘图。学院统计里的“读者数”使用nunique而不是count因为同一个读者可能借阅多次nunique才能避免重复计数。人均借阅量这个指标很容易被总借阅量大但读者数多的学院稀释所以前面必须同时计算两个基础值。3.3 热门图书和中图分类号的借阅排行热门图书榜是图书馆最看重的输出之一但直接value_counts书名只能得到单册图书排行无法回答“哪一类书借得多”。中图分类号的前一位或前两位代表学科大类适合用来观察馆藏结构是否合理# 直接统计书名借阅次数 top_books df[书名].value_counts().head(20) # 提取中图分类号前两位作为学科大类 df[分类大类] df[中图分类号].str[:2] cat_stats df.groupby(分类大类).agg( 借阅量(借书时间, count), 图书种类(图书条码, nunique) ).sort_values(借阅量, ascendingFalse) # 计算每类图书的平均单种借阅次数 cat_stats[单种均借量] cat_stats[借阅量] / cat_stats[图书种类]str[:2]对字符串列取前两个字符例如TP311变成TP。如果原始字段里有形如“TP311.56”的带点写法前两位提取仍然正确但如果分类号以字母开头个别条码写成小写需要先统一str.upper()。单种均借量是一个容易被忽视的指标它反映该类图书是否存在“少数几本被借爆多数书无人问津”的现象对采购决策比单纯借阅量更有参考价值。下表展示分类统计结果的典型样式实际运行时列名需与导出数据保持一致分类大类借阅量图书种类单种均借量TP1520032047.5I980056017.5O640041015.64. 借阅趋势预测、RFM读者分级与协同过滤推荐基础指标只能呈现历史规律想要让分析“往前走一步”需要引入建模环节。图书馆借阅数据分析里最常见的三类建模场景是预测未来借阅量、给读者价值分级、向读者推荐可能感兴趣的图书。这三类场景都不需要深度学习线性模型和经典协同过滤就足够。4.1 用移动平均和线性回归预测借阅趋势借阅量随学期呈周期性波动直接对原始序列做线性回归会忽略寒暑假导致的低谷。我先用移动平均平滑序列再对平滑后的趋势做短期预测# 按周统计借阅次数并做4周中心移动平均 weekly df.set_index(借书时间).resample(W).size() trend weekly.rolling(4, centerTrue).mean() # 把趋势数据转换为线性回归需要的二维特征 y trend.dropna() x np.arange(len(y)).reshape(-1, 1) from sklearn.linear_model import LinearRegression model LinearRegression() model.fit(x, y.values) # 预测未来4周的趋势值 future_x np.arange(len(y), len(y) 4).reshape(-1, 1) future_y model.predict(future_x)resample(W)按周分组统计借阅次数rolling(4, centerTrue).mean()计算四周中心移动平均能有效抹平单周异常波动。使用线性回归预测趋势前必须明确它只能捕捉整体线性方向无法预测期末考试周这种突发性高峰。实际使用时可以只把预测结果作为“业务基线”当真实值显著高于预测值时说明有临时性借阅活动发生。4.2 把RFM模型改造成借阅场景的读者分级RFM是电商客户分析的经典模型对应最近购买时间、购买频率和购买金额。借阅场景下没有金额我通常把“最近一次借阅时间”记为R“借阅次数”记为F“借阅图书种类”记为M三者用分位数打分后进行等级划分# 构造RFM基础数据 rfm_data df.groupby(借阅证号).agg( R(借书时间, max), # 最近借书时间 F(借书时间, count), # 借阅次数 M(图书条码, nunique) # 借阅过多少种书 ) # 计算最近一次借阅距离现在的天数 rfm_data[R] (pd.Timestamp.now() - rfm_data[R]).dt.days # 用四分位数给三项指标打分R越小越好F和M越多越好 rfm_data[R_score] pd.qcut(rfm_data[R], 4, labels[4, 3, 2, 1]).astype(int) rfm_data[F_score] pd.qcut(rfm_data[F].rank(methodfirst), 4, labels[1, 2, 3, 4]).astype(int) rfm_data[M_score] pd.qcut(rfm_data[M].rank(methodfirst), 4, labels[1, 2, 3, 4]).astype(int)pd.qcut按分位数分成4等份labels参数手动指定得分方向。R的分位数越大代表天数越多所以给它反转的得分标签。F和M存在大量并列值直接qcut会因为分位点重复而报错先.rank(methodfirst)给并列值分配不重复的排名再分箱就稳定了。RFM的结果不需要立刻定义复杂规则我一般先按“R_score高且F_score高”视为活跃读者“R_score低且F_score高”是潜在流失读者再结合M_score判断高价值读者。4.3 用物品协同过滤为“暂无借阅记录”的读者找书图书馆借阅场景和电商不同读者数量相对稳定图书生命周期长非常适合物品协同过滤。简化实现时不需要额外安装surprise库直接构造用户-图书矩阵并用余弦相似度计算图书之间的相似度# 构造用户-图书矩阵行是读者列是书名值为借阅次数 matrix df.pivot_table( index借阅证号, columns书名, values借阅次数, aggfuncsum, fill_value0 ) # 计算书名之间的余弦相似度 from sklearn.metrics.pairwise import cosine_similarity book_sim pd.DataFrame( cosine_similarity(matrix.T), indexmatrix.columns, columnsmatrix.columns ) # 给某个读者推荐找出他借过的书按相似度加权汇总 reader_borrow matrix[matrix.loc[A0001] 0] scores book_sim[reader_borrow.index].sum(axis1) scores scores[matrix.loc[A0001] 0] # 排除已借过的书 print(scores.sort_values(ascendingFalse).head(10))pivot_table把借阅记录转为二维矩阵缺失值填0。计算相似度时先对矩阵转置因为cosine_similarity默认计算行与行之间的相似度转置后每行才对应一本书。最后给读者推荐时用他借过的所有书的相似度分数求和排除已借书目后取最高的前十个。这个简化版没有去除流行度偏差实际项目中可以在相似度汇总时对热门图书降权例如乘以“平均借阅次数/该书借阅次数”的对数变换。5. 从结果到报表用matplotlib输出借阅分析图表与导出分析模块写完后整个项目最后一步是让管理员能直接看到结果。比起直接抛出一堆打印数据我习惯把核心图表组合成一张总览图并同时导出excel和html报表。5.1 可视化布局一图看懂核心借阅指标借阅趋势、读者分布和热门图书适合放在同一张大图里。绘图前必须先设置中文字体否则图例和标题会变成方块import matplotlib.pyplot as plt import matplotlib matplotlib.rcParams[font.sans-serif] [SimHei] # 设置中文字体 matplotlib.rcParams[axes.unicode_minus] False # 解决负号显示问题 plt.figure(figsize(12, 8)) # 子图1月度借阅趋势 plt.subplot(2, 2, 1) monthly df.set_index(借书时间).resample(M).size() monthly.plot(color#2E86AB) # 子图2借阅量前10的学院 plt.subplot(2, 2, 2) college_top college_stats[借阅总量].sort_values(ascendingFalse).head(10) college_top.plot.bar() # 子图3分类大类占比 plt.subplot(2, 2, 3) cat_stats.head(8)[借阅量].plot.pie(autopct%1.1f%%) plt.tight_layout() plt.savefig(library_analysis_report.png, dpi150)subplot把画布切分成2行2列前三个区域分别放趋势、学院柱状图和分类饼图。pandas的plot方法会自动使用DataFrame的索引作为横轴所以月度趋势和学院的排序要在进入绘图前完成。plt.tight_layout()避免子图之间标签重叠savefig导出高清png方便直接放到PPT或打印。5.2 把分析结果导出为excel和html报告代码运行的最终产出应该是结构化的报告文件。我用ExcelWriter把多个统计结果写到不同sheet同时用to_html生成一个浏览器可直接打开的简单报告目录with pd.ExcelWriter(借阅分析结果.xlsx) as writer: borrow_stats.to_excel(writer, sheet_name读者统计) college_stats.to_excel(writer, sheet_name学院统计) cat_stats.to_excel(writer, sheet_name图书分类统计) # 生成一个简单的html表格页 stats_html college_stats.to_html() with open(借阅分析报告.html, w, encodingutf-8) as f: f.write(fhtmlmeta charsetutf-8body{stats_html}/body/html)ExcelWriter上下文管理器会自动关闭并保存文件多个sheet之间互不影响。to_html把DataFrame转成html标签配合encodingutf-8保证中文正常显示。这里最大的坑是文件路径包含中文在部分windows环境下ExcelWriter会因为编码报错建议代码开头加import sys; sys.stdout.reconfigure(encodingutf-8)或统一用纯英文文件名再手动改中文名。本文还有配套的精品资源点击获取
返回列表