ARTICLE DETAIL

资讯详情

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

Joyful Pandas 综合实战:从 NumPy 向量化到集群日志分析的 7 道补充习题全解指南

Joyful Pandas 综合实战:从 NumPy 向量化到集群日志分析的 7 道补充习题全解指南 数据分析数据科学教程【免费下载链接】joyful-pandaspandas中文教程项目地址https://gitcode.com/datawhalechina/joyful-pandas点击查看免费下载导读本文以 Datawhale《Joyful Pandas》教程的 补充习题 为核心系统讲解 7 道贯穿 NumPy 向量化运算、pandas 分组聚合、连接合并、缺失数据与时序数据处理的综合实战题。文章完整继承原文档的全部题目要求、数据结构说明与输出格式约定并结合仓库中真实数据文件data/supplement 目录与正文十章内容source/Content逐题给出解题思路与函数选型建议。读完本文你将掌握零循环式向量化思维并能独立完成从成绩统计、商品审核到 35 万行集群日志分析的全流程数据任务。一、补充习题的定位与总体约束《Joyful Pandas》教程共十章分为基础知识、四类操作、四类数据三大模块参见 source/index.rst。每一章的章末习题均配有参考答案见 参考答案.ipynb 与 参考答案.rst而 补充习题 则是一组跨章节、面向真实场景的综合训练难度明显高于章末练习。补充习题有一个贯穿始终的硬性约束在补充习题中尽可能不要使用任何 for 或 while 循环。这意味着所有题目都要求用 NumPy 广播/向量化、pandas 的分组聚合groupby、变形pivot/melt、连接merge/join等声明式手段完成这正是 pandas 高效处理大数据集的精髓所在。全组习题共 7 道Ex1Ex7对应数据文件全部存放在仓库的 data/supplement 目录下目录结构如下ex2高三学生 16 次周测、期中、期末成绩CSV 共 18 个文件ex3商品信息与申请审核记录2 个 CSVex5四学区开课记录school_course.csvex7分布式集群日志logs.txt约 35 万行二、Ex1NumPy 的向量化运算Ex1 共含 4 道小题全部围绕 NumPy 的向量化、广播与高级索引展开对应正文 第一章 预备知识 中的数组构造、切片、ufunc 与广播机制。每道题都要求在不显式循环的前提下利用数组整体操作完成。2.1 找出缺失的最小正整数给定一个正整数列表找出其中缺失的最小正整数 arr np.array([2,3,4]) get_miss(arr) 1 arr np.array([6,3,5,1,2]) get_miss(arr) 4 arr np.array([5,2,1,3,4]) get_miss(arr) 6解题思路最小缺失正整数只可能落在[1, n1]区间内n 为数组长度。可借助np.arange(1, n1)与np.isin判断哪些候选数已在数组中再用np.argmax找到第一个不在的位置若全部存在答案即为n1。整个过程没有任何显式循环仅靠数组之间的集合运算完成。2.2 构造阶梯连续填充数组设计函数get_res(n)生成二维 NumPy 数组构造规则如下第 1 行填入 1 个 1第 2 行在上一行最后填入位置的下一列开始连续填入 2 个 2第 3 行在第二行最后一个填入位置的下一列连续填入 3 个 3……第 n 行连续填入 n 个 n。 n 4 get_res(n) array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 2., 2., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 3., 3., 3., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 4., 4., 4., 4.]])解题思路观察可知每一行的起始列号满足递推关系start_i start_{i-1} (i-1)即第 i 行起始列等于前 i-1 行的元素总数。因此各行的起始列可由np.cumsum一次性求出再借助 NumPy 的高级索引将行号、起始列与填充值组装为索引数组批量赋值。行数 n 与总元素数n(n1)/2共同决定了数组宽度可用(n*(n1)//2)计算。2.3 简单随机游走的极限估计点 A 从数轴原点出发进行 n 步简单随机游走每步等概率向左或向右移动 1 个单位最终位置记为S_n。数学上可以证明lim(n→∞) E|S_n| / √n √(2/π)现取 n5000进行 1000 次试验每次试验以(1/100)·Σ|S_n|近似E|S_n|。请计算 1000 个极限估计值即估计值 - √(2/π)的均值、0.05 分位数与 0.95 分位数。解题思路一次试验的 5000 步可用np.random.choice或np.random.randint一次性生成±1的步长数组再cumsum得到每步后的位置末位即为S_n。1000 次试验可进一步合并为(1000, 5000)的二维数组整体完成最后用np.mean与np.percentile(…, [5, 95])得到三个统计量。该题是对 ch1.rst 中随机数、cumsum 与广播机制的综合演练。2.4 计算带距离排名的相关矩阵二维平面上有 n 个点每个点有 k 维特征。坐标存于node_xy形状(n, 2)特征存于node_fea形状(n, k)。点 a 与点 b 的相关度定义为S_ab σ_ab / 2 λ_ab / 2其中 σ_ab 是特征向量的余弦相似度σ_ab Σ A_i·B_i / (√ΣA_i² · √ΣB_i²)而 λ_ab 基于平面距离排名将点到点 a 的二维距离排序距离最近排名 1的是点 a 自身记点 b 的排名为r_b^(a)则λ_ab 1 - 2·(r_b^(a) - 1) / (n - 1) n, k 1000, 10 node_xy np.random.rand(n, 2) node_fea np.random.rand(n, k) get_S(node_xy, node_fea)解题思路题干提示使用np.argsort()σ 矩阵利用广播一次算出(n, n)的成对余弦相似度。核心是把特征矩阵归一化后做矩阵乘法node_fea / np.linalg.norm(node_fea, axis1, keepdimsTrue)再与自身转置相乘即F F.T。λ 矩阵先算(n, n)的成对欧氏距离可用(xy²).sum(1)的广播展开式或scipy.spatial.distance的 pdist 思路再用np.argsort沿每一行得到距离排名最后按公式换算为 λ。最终S (σ λ) / 2。全程零循环复杂度为O(n²·k)与无 for/while的约束完全契合。三、Ex2统计学生的成绩情况3.1 数据结构说明data/supplement/ex2 目录存放某校高三第一学期的成绩包含16 次周测、期中、期末共 18 张 CSV每张表结构一致df pd.read_csv(data/supplement/ex2/第1次周测成绩.csv) df.head()经实测每张表为896 行 × 7 列列名为班级, 姓名, 选科, 语文, 数学, 英语, 科目。其中科目一栏表示学生选科的成绩如选物理则科目为该生物理分。班级编号为 111 共 11 个班选科为 6 门物理、化学、生物、历史、地理、政治。所有表中相同的行表示同一位同学这是跨表计算的前提。3.2 五个子问题问题 1是否存在姓名相同的学生直接对姓名做duplicated()判断即可属于 第二章 pandas基础 中重复值处理的应用。问题 2第一次周测各班选修物理或化学同学的语数英总分均值哪个班最高先按选科.isin([物理,化学])过滤再groupby(班级)对语数英三列求和最后取平均。这里需要把三科先合并成总分再按班级聚合对应 第四章 分组 的分组聚合操作。问题 3学期总评前十总评 各次考试总分的加权平均其中周测权重 50%16 次均分每次 3.125%、期中 20%、期末 30%。计算流程将 16 次周测表、期中表、期末表按行拼接为一张考试-学生长表涉及 第六章 连接 或 concat按学生及班级、选科分组计算各次考试总分对周测总分取平均 × 50% 期中 × 20% 期末 × 30% 得到总评题干明确要求结合nlargest函数找出年级总评前十的同学即groupby(...)[总评].sum()后接.nlargest(10)。问题 418 班文理科期末总分前 5物化生为理科、政史地为文科。需按班级 文理分科两维分组取期末总分语数英 科目分前 5并输出指定格式pd.DataFrame( { 1班文: [王大锤历史102][...]* 4, 1班理: [...]* 5, 2班文: [...]* 5, ...: [...]* 5, 8班理: [...]* 5, } ) # 王大锤历史102只是举个例子表示结果字符串需要按照这个格式来写即每个单元格是姓名选科选科分数这样的格式化字符串可用str.format或 f-string 拼接配合nlargest完成。问题 5成绩稳定性排名标准差以每次考试在全年级相同选科学生中的总分排名标准差度量稳定性。思路对每一次考试先在同一选科组内按总分rank()method 可选 min 或 dense得到学生当次年级排名将所有考试的排名按学生纵向堆叠按班级 × 选科分组求排名标准差最后汇总为每个班级、每门选科一个稳定性均值。期望输出为一个 11 行班级 111× 6 列物理、化学、生物、历史、地理、政治的 DataFramepd.DataFrame( np.random.rand(11, 6), indexpd.Index(range(1, 12), name班级), columnspd.Index( [物理, 化学, 生物, 历史, 地理, 政治], name选科, ) )该题综合考察 分组聚合、rank 排名 与 长宽表变形pivot/unstack 把长表转为班级×选科的宽表。四、Ex3统计商品的审核情况4.1 数据结构说明data/supplement/ex3 目录包含两张表商品信息.csvID号, 识别码, 类别共 26832 行ID 从ID 000001开始类别为 7 种T1/T2/Q1/Q2/S1/S2/S3。申请与审核记录.csvID号, 申请人, 申请时间, 审核人, 审核时间, 结果共 147500 行结果只有通过与未通过两种。df_info pd.read_csv(data/supplement/ex3/商品信息.csv) df_info.head() df_record pd.read_csv(data/supplement/ex3/申请与审核记录.csv) df_record.head()审核流程申请人发起申请 → 审核人审核 → 通过或未通过未通过则可换一位申请人再次申请直至通过。注意申请人、审核人均为\#3((52\{这类含转义符的特殊字符串读取时需原样保留。4.2 五个子问题问题 1有多少商品最终通过审核一个商品可能有多条记录最终通过指该商品存在结果为通过的记录。可先对df_record按ID号分组判断是否出现通过再与df_info连接统计满足条件的商品数。问题 2各类别商品的通过率通过率 该类别最终通过的商品数 / 该类别商品总数。需要把审核记录与商品信息按ID号合并再groupby(类别)计算比例典型的一对多连接 分组聚合。问题 3类别为 T1 且最终通过的商品的平均审核次数先筛选类别 T1且最终通过的商品再统计这些商品在审核记录中出现的记录条数即审核次数取平均。同一商品的多条申请在 连接 后会出现多行统计次数需按ID号计数。问题 4是否存在上一次审核未完成时就提交下一次申请的情况这里的审核未完成需结合时间推断比较同一条目相邻两次申请的申请时间与上一次的审核时间。若某条记录的申请时间早于上一记录的审核时间说明上一次审核尚未完成就发起了新申请。可用groupby(ID号)配合shift()取上一行审核时间再做逐行比较。问题 5统计通过商品的第一位申请人与最后一位审核人对最终通过的商品输出其第一条申请记录中的申请人和最后一条记录即通过那条中的审核人pd.DataFrame( { ID号: [ID 000001][...]*3, 类别:[T1][...]*3, 申请人:[\#3((52\{][...]*3, 审核人:[3}04}%75][...]*3 }, index[1,2,3,...] )题干给出的提示是关键groupby 对象上也定义了 head 和 tail 方法。也就是说只需按ID号分组后分别取各组的head(1)第一位申请人与tail(1)最后一位审核人再与商品信息合并即可完全无需循环。五、Ex4删除同样的行现有两张表df16 行与df23 行请在df1中剔除在df2中出现过的行df1 pd.DataFrame({ A: [3,2,2,3,1,3], B: [2,1,1,3,6,2], C: [1,2,2,7,7,1], D: [5,6,6,1,2,5], }) df2 pd.DataFrame({ A: [2,3,1], B: [1,9,6], C: [2,7,7], D: [6,1,2], })注意df2的第 2 行(3,9,7,1)与df1的第 4 行(3,3,7,1)只在 B 列不同因此不会被剔除df2第 3 行(1,6,7,2)与df1第 5 行完全相同应被删除。最终结果应保留df1的第 1、4、6 行pd.DataFrame({ A: [3,3,3], B: [2,3,2], C: [1,7,1], D: [5,1,5], })解题思路这是典型的集合差操作。方法一是为两张表各加一列原始行号用merge(..., howleft, indicatorTrue)标记哪些行在df2中存在再过滤方法二是把两张表concat后按全部列drop_duplicates(keepFalse)。前者对应 第六章 连接 的关系连接后者对应 第二章 的重复值处理两种方案都能做到零循环。六、Ex5统计每个学区的开课数量某城市共4 个学区area_1area_4每个学区有若干学校学校名字互不相同。数据文件 school_course.csv 共 1921 行列为Area, School, Coursedf pd.read_csv(data/supplement/ex5/school_course.csv) df.head()字段语义要点原文档已明确每条记录是某学校开设的一门课一个学校可有多条记录单条记录内部的课程不会重复但一条记录可能包含多个课程如course_9 course_40 course_100用空格分隔同一学校不同记录之间的课程可能重复课程共 100 门编号为course_1course_100。题目要求统计每个学区开设了某门课程的学校数量同一学校在一门课上无论出现多少条记录都只计 1 次。输出为 100 行 × 4 列的矩阵res pd.DataFrame( 0, index[course_%d%(i1) for i in range(100)], columns[area_%d%(i1) for i in range(4)] ) res.head() # 若area_1共有20所学校开设了course_1则第一个单元格为20解题思路这是典型的分组 去重 计数 透视问题先把Course列按空格str.split拆开并explode成一行一课涉及 第八章 文本数据 与长表变形对(Area, School, Course)三列drop_duplicates()保证同一学校同一课程只计一次groupby([Course, Area]).size()统计每学区开课学校数用unstack将 Area 展开为 4 列再reindex补齐全部 100 门课缺课填 0对应 第九章 分类数据 的类别完整性思想。七、Ex6捕获非零的行列索引给定如下 4×3 数据框返回所有非零元素的行列组合构成的多级索引df pd.DataFrame( [[0,5,0],[2,1,0],[0,0,6],[0,9,0]], indexlist(ABCD), columnslist(XYZ)) df期望结果是一个 MultiIndex每个元素为(列名, 行名)对按列分组、按行排序res pd.Index([ (X, B), (Y, A), (Y, B), (Y, D), (Z, C)]) res即 X 列的非零行是 BY 列的非零行是 A、B、DZ 列的非零行是 C。解题思路关键在于把行列索引变成可操作的数据。推荐做法用df.stack()把宽表变成长表行索引变成 MultiIndex(行, 列)用df[df ! 0].stack()直接过滤掉 0 值取结果的索引交换层级swaplevel或重新组合为(列, 行)顺序再sort_index()排序。stack属于 第五章 变形 中索引间变形的核心操作此题正是它的典型应用场景。八、Ex7分析集群日志大数据综合压轴题8.1 数据背景与日志格式某公司分布式文件集群由134 台服务器构成分布在 5 个机房R0 机房 23 台、R1 机房 16 台、R2 机房 47 台、R3 机房 30 台、R4 机房 18 台每个机房的服务器编号从 001 开始。日志文件 logs.txt 记录了 2022 年 9 月 27 日的全部文件传输历史共 350668 行每行格式如下[PUSH|2022-09-27 07:08:12] Cluster#R1#007 | tgfuHOAjDJ | 4.41 GB [SAVE|2022-09-27 08:17:00] Cluster#R0#019 | neLAGbGkvd | 7.99 GB字段语义PUSH向其他服务器发出文件SAVE接收其他服务器文件Cluster#R?#???机器编号如Cluster#R4#014表示 R4 机房第 14 号机器十位字符串文件唯一标识file_id末尾数值PUSH 为发出大小SAVE 为接收大小单位混用 GB 与 MB若某个 SAVE 记录接收了文件 XXX必然存在另一台机器 PUSH 该文件 XXX 的记录同一对 PUSH 与 SAVE 记录的文件大小不一致 → 本次传输最终处于未完成状态Unfinished。读取预览with open(data/supplement/ex7/logs.txt, r) as f: for i, txt in enumerate(f.readlines()): if i 5: break print(txt.strip())8.2 子问题一提取与清洗日志构成长表使用高效方法提取日志信息注意脏数据清洗如时间格式错误、无效数字整理为如下格式push_time按时间顺序pd.DataFrame( { file_id: [wfjqoIDhsD, QigjDSEGje, ...], file_size: [6.35, 149.23, ...], save_size: [6.32, np.nan, ...], # np.nan表示没收到 push_from: [A3-007, A0-017, ...], push_to: [A2-012, np.nan, ...], # np.nan表示没收到 push_time: pd.to_datetime([ 20220927 01:03:55, 20220927 01:03:58, pd.NaT]), save_time: pd.to_datetime([ 20220927 01:03:57, pd.NaT, pd.NaT]), }, index[0, 1, ...] ) # 数据仅为格式参考不代表真实数据解题思路本题本质是对 35 万行文本做正则解析 长表变换。要点包括用正则一次性提取操作类型、时间、机器号、file_id、大小与单位涉及 第八章 文本数据 的str.extract将大小统一换算为同一单位GB→MB 或反之用pd.to_numeric(errorscoerce)清洗无效数字把机器号进一步拆出机房号与机内编号PUSH 与 SAVE 两类记录分别成表再按file_id做一对一连接题干提示本质上是把两个一一对应的文件信息进行连接未配对的缺失方以np.nan/NaT填充。8.3 子问题二机房间平均传输速度一般而言同机房内传输比跨机房快。请对所有传输完成的文件按源机房 × 目标机房计算平均传输速度MB/spd.DataFrame( np.random.rand(25).reshape(5, -1), index[R%d%i for i in range(5)], columns[R%d%i for i in range(5)], ) # 数据仅为格式参考不代表真实数据第 i 行第 j 列表示从机房 i 传到机房 j 的完成文件的平均速度。需要回答对角线值是否高于非对角线值解题思路速度为file_size / 传输耗时耗时 save_time - push_time时间差对象见 第十章 时序数据 的时间差部分。先过滤 Finished 文件用groupby([push机房, push_to机房])聚合均值再unstack为 5×5 矩阵。结论需基于真实数据的计算结果得出不要凭经验断言。8.4 子问题三按机房统计传输状态比例题干定义了三种传输状态Finished文件大小等于接收大小传输成功Missed日志中只有单条记录仅 PUSH 或仅 SAVE文件未送达Unfinished文件大小不等于接收大小再按传输比例接收大小/发送大小分三档Unfinished-Almost比例 90%Unfinished-Fair比例 50%Unfinished-Bad其余。计算每个机房的最终状态比例结果先按 Status 排序Finished Unfinished-Almost Unfinished-Fair Unfinished-Bad Missed再按机房号排序pd.DataFrame( { Status: [Finished]*3 [...] [Missed], Room: [R0, R1, R2, ..., R5], Ratio: [0.1, 0.15, 0.1, ..., 0.05], }, index[0,1,2,...,24] )解题思路状态判断是行内多条件映射可先用np.select或pd.cut对每一对 PUSH/SAVE 记录打标签属于 分组聚合 前期的向量化计算再按发送方机房分组统计各状态占比最终排序用Categorical定义 Status 的顺序或给状态赋数值权重后sort_values。8.5 子问题四按小时统计大文件收发差按小时计算每个机房发送的大文件数与接收的大文件数之差其中大文件指大小超过800M的文件。行索引是时间列索引是机房。解题思路先过滤大小 800M 的记录按(小时, 机房)分组分别统计 PUSH 数与 SAVE 数再相减并unstack成时间 × 机房宽表。时间分桶可用 第十章 的dt.floor(h)或resample(h)完成。8.6 子问题五按小时计算每台机器的空闲率对每一台机器空闲时间指其既不在发送任务中、也不在接收任务中的时间每个小时的空闲率 该小时内空闲时间占比。行索引是时间列索引是机器134 台。解题思路这是全组习题中难度最高的一题。其核心是把每台机器的一次次忙碌区间从 PUSH/SAVE 开始时刻到结束时刻看作时间区间先做区间合并merge intervals再反算空闲时长。题干给出的提示非常关键本题涉及到了区间合并问题pandas 的区间索引没有定义类似于 merge intervals 的函数请阅读相关的实现来思考如何实现这个功能。由于 pandas 的IntervalIndex未内置区间合并函数需要借助区间端点排序 栈式扫描的思路自行实现如按开始时间排序、维护当前最右端点合并重叠区间再按小时切片统计总忙碌时长、用1 - 忙碌/3600s得到空闲率。该题综合考验时序数据、区间运算与自定义向量化函数的能力是 第十章 时序数据 知识点的极限延伸。九、知识图谱补充习题与教程正文的映射7 道补充习题并非孤立题目而是与教程十章内容一一呼应构成一条完整的能力验证链路补充习题核心考点对应教程章节Ex1向量化、广播、argsort、cumsum、percentilech1 预备知识NumPyEx2多表拼接、groupby 聚合、nlargest、rank、变形ch2、ch4、ch5Ex3一对多连接、groupby 的 head/tail、时序比较ch4、ch6Ex4集合差 / 关系连接 / 去重ch2、ch6Ex5文本拆分、explode、去重计数、unstackch5、ch8、ch9Ex6stack 索引间变形、多级索引构造ch3、ch5Ex7正则清洗、一对多连接、时序、区间合并ch6、ch8、ch10若完成全部七题后仍需要参考答案形态的参照章末习题的完整解答可参考 notebook/参考答案.ipynb 或 参考答案.html注意补充习题本身不提供官方答案解题过程需独立完成这也是其作为进阶挑战的设计意图。十、总结补充习题是《Joyful Pandas》教程的毕业考试从 6 行小表的集合运算到 896 行成绩表的加权排名再到 26 万商品审核记录的多轮状态追踪与 35 万行集群日志的区间合并分析难度逐级递进。贯穿始终的禁止 for/while 循环约束迫使读者用 NumPy 广播、pandas 分组聚合、长宽变形、关系连接与时序窗口这些语言级能力去解决问题——这正是 pandas 在大数据场景下保持性能的根本原因。建议读者按 Ex1 → Ex7 的顺序依次攻克每完成一题都回到 source/Content 对应的章节复盘知识盲区将会用升级为用得对、用得快。赞分享数据分析数据科学教程【免费下载链接】joyful-pandaspandas中文教程项目地址https://gitcode.com/datawhalechina/joyful-pandas点击查看免费下载相关推荐joyful-pandas 全十章练习参考答案精讲从 NumPy 向量化到 pandas 高阶数据操作joyful pandas 全十章练习参考答案精讲从 NumPy 向量化到 pandas 高阶数据操作 《joyful pandas》是一份以实战练习驱动的数据分析数据科学教程Joyful Pandas的实战应用从数据清洗到深度分析的全流程指南Joyful Pandas的实战应用从数据清洗到深度分析的全流程指南 引言为什么选择Joyful Pandas 在数据科学和数据分析的日常工作中pand数据分析数据科学教程Nacos集群网络连接异常问题分析与解决方案Nacos集群网络连接异常问题分析与解决方案 问题现象 在使用Nacos 2.2.1版本集群时客户端应用会偶发出现Request stream error,后端微服务配置中心服务注册发现云原生上一篇我的十年青春差点消失GetQzonehistory免费完整备份QQ空间历史说说全记录下一篇GetQzonehistory完整备份教程把QQ空间十年说说打包带回家创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表