补充习题#

In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: import matplotlib.pyplot as plt

注意

在补充习题中不得使用任何for循环。

Ex1:NumPy的向量化运算#

  • 给定一个正整数列表,请找出缺失的最小正整数。

>>> 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
  • 设计一个生成二维NumPy数组的函数get_res(),其输入为正整数n,返回的数组构造方式如下:第1行填入1个1,第2行在上一行填入位置的下一列连续填入2个2,第3行在第二行最后一个填入位置的下一列连续填入3个3,…,第n行在第n-1行最后一个填入位置的下一列连续填入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.]])
  • \(A\) 初始位置在数轴原点处,现进行n步简单随机游走,即每一步以等概率向左或向右移动长度为1的距离,记该点最终的位置为 \(S_n\) ,则可以证明

\[\lim_{n\rightarrow+\infty}\frac{\mathbb{E}|S_n|}{\sqrt{n}}=\sqrt{\frac{2}{\pi}}\]

现取n为5000进行1000次试验,且每次试验中用 \(\frac{1}{100}\sum_{k=1}^{100}|S_n|\) 来代替 \(\mathbb{E}|S_n|\) 。此时可以计算得到1000个 \(\lim_{n\rightarrow+\infty}\frac{\mathbb{E}|S_n|}{\sqrt{n}}-\sqrt{\frac{2}{\pi}}\) 的估计值,请计算这些估计值的均值、0.05分位数和0.95分位数。

  • 在二维平面上有n个点,每个点具有k维特征,点的坐标数据记录在node_xy中,点的特征数据记录在node_fea中。现要计算所有点的相关矩阵 \(S\) ,点a和点b的相关系数定义如下

\[S_{ab} = \frac{\sigma_{ab}}{2} + \frac{\lambda_{ab}}{2}\]

其中,若记点a特征为 \(A\) ,点b特征为 \(B\) ,则有

\[\sigma_{ab} = \frac{\sum_{i=1}^kA_iB_i}{\sqrt{\sum_{i=1}^kA^2_i}\sqrt{\sum_{i=1}^kB^2_i}}\]

对于点a而言,将所有点到点a的二维平面距离进行排序,从而得到每个点到点a的距离排名,距离最近(排名为1)的点是点a自身,记点b的排名为 \(r^{(a)}_b\) ,则定义

\[\lambda_{ab} = 1 - \frac{2\times (r^{(a)}_b-1)}{n-1}\]

请对于给定的node_xy和node_fea计算相关矩阵 \(S\) 。(提示:使用np.argsort())

>>> n, k = 1000, 10
>>> node_xy = np.random.rand(n, 2)
>>> node_fea = np.random.rand(n, k)
>>> get_S(node_xy, node_fea)

Ex2:统计学生的成绩情况#

在data/supplement/ex2目录下存放了某校高三第一学期的学生成绩情况,包含16次周测成绩、期中考试成绩和期末考试成绩,科目一栏的成绩表示学生选课的成绩。所有的表中,相同的行表示的是同一位同学。请完成以下练习:

In [4]: df = pd.read_csv('data/supplement/ex2/第1次周测成绩.csv')

In [5]: df.head()
Out[5]: 
   班级   姓名  选科   语文  数学   英语  科目
0   1   吴刚  地理   93  95   82  69
1   1   卢楠  物理  108  77   90  94
2   1  唐秀兰  历史   88  72   95  85
3   1   张刚  化学   85  88  102  76
4   1   姜洋  历史  104  99   84  86
  • 该校高三年级中是否存在姓名相同的学生?

  • 在第一次周测中,请求出每个班级选修物理或化学同学的语数英总分的平均值。哪个班级最高?

  • 学生在该学期的总评计算方式是各次考试总分的加权平均值,其中周测成绩权重为50%(每次测验权重相等,即3.125%),期中权重为20%,期末权重为30%。请结合nlargest函数找出年级中总评前十的同学。

  • 请统计1班到8班文理科(物化生为理科,政史地为文科)期末考试总分前5的学生,结果格式如下,括号内的为选科分数:

In [6]: pd.DataFrame(
   ...:     {
   ...:         "1班(文)": ["王大锤:历史(102)"]+["..."]* 4,
   ...:         "1班(理)": ["..."]* 5,
   ...:         "2班(文)": ["..."]* 5,
   ...:         "...": ["..."]* 5,
   ...:         "8班(理)": ["..."]* 5,
   ...:     }
   ...: ) # 王大锤:历史(102)只是举个例子,表示结果字符串需要按照这个格式来写
   ...: 
Out[6]: 
         1班(文) 1班(理) 2班(文)  ... 8班(理)
0  王大锤:历史(102)   ...   ...  ...   ...
1          ...   ...   ...  ...   ...
2          ...   ...   ...  ...   ...
3          ...   ...   ...  ...   ...
4          ...   ...   ...  ...   ...
  • 学生成绩的稳定性可以用每次考试在全年级相同选科学生中的总分排名标准差来度量,请计算每个班级的各科学生成绩稳定性的均值,结果格式如下:

In [7]: pd.DataFrame(
   ...:     np.random.rand(11, 6),
   ...:     index=pd.Index(range(1, 12), name="班级"),
   ...:     columns=pd.Index(
   ...:         ["物理", "化学", "生物", "历史", "地理", "政治"],
   ...:         name="选科",
   ...:     )
   ...: )
   ...: 
Out[7]: 
选科        物理        化学        生物        历史        地理        政治
班级                                                            
1   0.461479  0.780529  0.118274  0.639921  0.143353  0.944669
2   0.521848  0.414662  0.264556  0.774234  0.456150  0.568434
3   0.018790  0.617635  0.612096  0.616934  0.943748  0.681820
4   0.359508  0.437032  0.697631  0.060225  0.666767  0.670638
5   0.210383  0.128926  0.315428  0.363711  0.570197  0.438602
6   0.988374  0.102045  0.208877  0.161310  0.653108  0.253292
7   0.466311  0.244426  0.158970  0.110375  0.656330  0.138183
8   0.196582  0.368725  0.820993  0.097101  0.837945  0.096098
9   0.976459  0.468651  0.976761  0.604846  0.739264  0.039188
10  0.282807  0.120197  0.296140  0.118728  0.317983  0.414263
11  0.064147  0.692472  0.566601  0.265389  0.523248  0.093941

Ex3:统计商品的审核情况#

在data/supplement/ex3中存放了两个有关商品审核的信息表,“商品信息.csv”中记录了每个商品的ID号,唯一的识别码以及商品所属的类别,“申请与审核记录.csv”中记录了每个商品的审核信息。已知商品的审核流程如下:由申请人发起商品审核的申请,然后由审核人审核,审核的结果包括通过与不通过两种情况,若商品不通过审核则可以由另一位申请人再次发起申请,直到商品的审核通过。

In [8]: df_info = pd.read_csv('data/supplement/ex3/商品信息.csv')

In [9]: df_info.head()
Out[9]: 
         ID号      识别码  类别
0  ID 000001  CRtXJUK  T1
1  ID 000002  RGSxifC  Q1
2  ID 000003  AboduTp  S1
3  ID 000004  zlpUeMl  S2
4  ID 000005  IVQqhIK  S3

In [10]: df_record = pd.read_csv('data/supplement/ex3/申请与审核记录.csv')

In [11]: df_record.head()
Out[11]: 
         ID号         申请人        申请时间         审核人        审核时间   结果
0  ID 000001  \#+3((52\{  2020-04-19  ~1=6\*183|  2020-05-03  未通过
1  ID 000001  8@75[1|2\*  2020-05-10  15![3\({59  2020-07-17  未通过
2  ID 000001  }!7)(#^0*7  2020-07-28  3`}04}%@75  2020-08-23   通过
3  ID 000002  |*{20#9|}5  2020-01-05  ={`8]03*4+  2020-03-09  未通过
4  ID 000002  4~6%)455`[  2020-03-14  =$-36[)|8]  2020-04-21  未通过
  • 有多少商品最终通过审核?

  • 各类别商品的通过率分别为多少?

  • 对于类别为“T1”且最终状态为通过的商品,平均审核次数为多少?

  • 是否存在商品在上一次审核未完成时就提交了下一次审核申请?

  • 请对所有审核通过的商品统计第一位申请人和最后一位审核人的信息,返回格式如下:

In [12]: pd.DataFrame(
   ....:     {
   ....:         "ID号": ["ID 000001"]+["..."]*3,
   ....:         "类别":["T1"]+["..."]*3,
   ....:         "申请人":["\#+3((52\{"]+["..."]*3,
   ....:         "审核人":["3`}04}%@75"]+["..."]*3
   ....:     },
   ....:     index=[1,2,3,"..."]
   ....: )
   ....: 
Out[12]: 
           ID号   类别         申请人         审核人
1    ID 000001   T1  \#+3((52\{  3`}04}%@75
2          ...  ...         ...         ...
3          ...  ...         ...         ...
...        ...  ...         ...         ...

提示

groupby对象上也定义了head和tail方法。

Ex4:删除同样的行#

现有两张表,请在df1中剔除在df2中出现过的行。

In [13]: 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],
   ....: })
   ....: 

In [14]: df1
Out[14]: 
   A  B  C  D
0  3  2  1  5
1  2  1  2  6
2  2  1  2  6
3  3  3  7  1
4  1  6  7  2
5  3  2  1  5

In [15]: df2 = pd.DataFrame({
   ....:     "A": [2,3,1],
   ....:     "B": [1,9,6],
   ....:     "C": [2,7,7],
   ....:     "D": [6,1,2],
   ....: })
   ....: 

In [16]: df2
Out[16]: 
   A  B  C  D
0  2  1  2  6
1  3  9  7  1
2  1  6  7  2

结果应当如下:

In [17]: pd.DataFrame({
   ....:     "A": [3,3,3],
   ....:     "B": [2,3,2],
   ....:     "C": [1,7,1],
   ....:     "D": [5,1,5],
   ....: })
   ....: 
Out[17]: 
   A  B  C  D
0  3  2  1  5
1  3  3  7  1
2  3  2  1  5

Ex5:统计每个学区的开课数量#

某个城市共有4个学区,每个学区有若干学校,学校之间名字互不相同。每一条记录为该学校开设的课程,一个学校可能有多条记录,每一条记录内部的课程不会重复,但同一学校不同记录之间的课程可能重复。

In [18]: df = pd.read_csv('data/supplement/ex5/school_course.csv')

In [19]: df.head()
Out[19]: 
     Area      School                         Course
0  area_1   school_99                      course_90
1  area_2   school_32                      course_20
2  area_3   school_64                      course_38
3  area_1  school_231  course_9 course_40 course_100
4  area_3  school_147  course_57 course_77 course_28

课程的种类共有100门,编号为”school_1”到”school_100”。现要统计每个学区各项课程的开设学校数量,结果如下格式:

In [20]: res = pd.DataFrame(
   ....:     0, index=["course_%d"%(i+1) for i in range(100)],
   ....:     columns=["area_%d"%(i+1) for i in range(4)]
   ....: )
   ....: 

In [21]: res.head() # 若area_1共有20所学校开设了course_1,则第一个单元格为20
Out[21]: 
          area_1  area_2  area_3  area_4
course_1       0       0       0       0
course_2       0       0       0       0
course_3       0       0       0       0
course_4       0       0       0       0
course_5       0       0       0       0

Ex6:捕获非零的行列索引#

给定如下的数据框,请返回非零行列组合构成的多级索引。

In [22]: df = pd.DataFrame(
   ....:     [[0,5,0],[2,1,0],[0,0,6],[0,9,0]],
   ....:     index=list("ABCD"), columns=list("XYZ"))
   ....: 

In [23]: df
Out[23]: 
   X  Y  Z
A  0  5  0
B  2  1  0
C  0  0  6
D  0  9  0

In [24]: res = pd.Index([
   ....:     ('X', 'B'),
   ....:     ('Y', 'A'),
   ....:     ('Y', 'B'),
   ....:     ('Y', 'D'),
   ....:     ('Z', 'C')])
   ....: 

In [25]: res
Out[25]: 
MultiIndex([('X', 'B'),
            ('Y', 'A'),
            ('Y', 'B'),
            ('Y', 'D'),
            ('Z', 'C')],
           )