15,Python数分之Pandas训练,力扣,1412. 查找成绩处于中游的学生

  • 学习:知识的初次邂逅
  • 复习:知识的温故知新
  • 练习:知识的实践应用

目录

一,原题力扣链接

二,题干

三,建表语句

四,分析

五,Pandas解答

六,验证

七,知识点总结


一,原题力扣链接

. - 力扣(LeetCode)

二,题干

表: Student

+---------------------+---------+
| Column Name         | Type    |
+---------------------+---------+
| student_id          | int     |
| student_name        | varchar |
+---------------------+---------+
student_id 是该表主键(具有唯一值的列)。
student_name 学生名字。

表: Exam

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| exam_id       | int     |
| student_id    | int     |
| score         | int     |
+---------------+---------+
(exam_id, student_id) 是该表主键(具有唯一值的列的组合)。
学生 student_id 在测验 exam_id 中得分为 score。

成绩处于中游的学生是指至少参加了一次测验, 且得分既不是最高分也不是最低分的学生。

编写解决方案,找出在 所有 测验中都处于中游的学生 (student_id, student_name)。不要返回从来没有参加过测验的学生。

返回结果表按照 student_id 排序。

返回结果格式如下。

示例 1:

输入:
Student 表:
+-------------+---------------+
| student_id  | student_name  |
+-------------+---------------+
| 1           | Daniel        |
| 2           | Jade          |
| 3           | Stella        |
| 4           | Jonathan      |
| 5           | Will          |
+-------------+---------------+
Exam 表:
+------------+--------------+-----------+
| exam_id    | student_id   | score     |
+------------+--------------+-----------+
| 10         |     1        |    70     |
| 10         |     2        |    80     |
| 10         |     3        |    90     |
| 20         |     1        |    80     |
| 30         |     1        |    70     |
| 30         |     3        |    80     |
| 30         |     4        |    90     |
| 40         |     1        |    60     |
| 40         |     2        |    70     |
| 40         |     4        |    80     |
+------------+--------------+-----------+
输出:
+-------------+---------------+
| student_id  | student_name  |
+-------------+---------------+
| 2           | Jade          |
+-------------+---------------+
解释:
对于测验 1: 学生 1 和 3 分别获得了最低分和最高分。
对于测验 2: 学生 1 既获得了最高分, 也获得了最低分。
对于测验 3 和 4: 学生 1 和 4 分别获得了最低分和最高分。
学生 2 和 5 没有在任一场测验中获得了最高分或者最低分。
因为学生 5 从来没有参加过任何测验, 所以他被排除于结果表。
由此, 我们仅仅返回学生 2 的信息。

三,建表语句

import pandas as pd

# 创建学生数据
student_data = {
    'student_id': [1, 2, 3, 4, 5, 6, 7],
    'student_name': ['Anna', 'Jhon', 'Jade', 'Maria', 'Winston', 'Elvis', 'Jaze']
}
student = pd.DataFrame(student_data)

# 创建考试数据
exam_data = {
    'exam_id': [10, 10, 10, 10, 20, 20, 20, 20, 20, 30, 30, 30, 40, 40, 50, 50, 50, 60, 60, 60, 60, 60, 70],
    'student_id': [1, 4, 5, 6, 1, 2, 3, 5, 7, 1, 2, 5, 3, 7, 5, 6, 7, 2, 3, 4, 5, 7, 5],
    'score': [35, 64, 68, 68, 38, 52, 59, 76, 84, 32, 57, 66, 41, 61, 34, 56, 63, 53, 53, 73, 73, 78, 49]
}
exam = pd.DataFrame(exam_data)
student

四,分析

题解:

表1:学生表 

字段:学生id,学生姓名

表2:测验表

字段:测验次数,学生id,分数

成绩处于中游的学生是指至少参加了一次测验, 且得分既不是最高分也不是最低分的学生。

编写解决方案,找出在 所有 测验中都处于中游的学生 (student_id, student_name)。不要返回从来没有参加过测验的学生。

返回结果表按照 student_id 排序。

第一步:合并两个表

#第一步合并两个表
df = pd.merge(student,exam,on='student_id')
df

 

第二步:给最高分排序 生成一个新列  排序考虑并列

#第二步 给最高分排序
df = df.sort_values(['exam_id','score'],ascending=[True,False])
df['rn'] = df.groupby('exam_id')['score'].rank(method='dense',ascending=False)  #允许并列
df

第三步,开一个最低分的列 给每次测验的排序 最低分优先 考虑并列

#第二步 给最低分排序
df = df.sort_values(['exam_id','score'],ascending=[True,True])
df['rn1'] = df.groupby('exam_id')['score'].rank(method='dense',ascending=True)  #允许并列
df

 

第四步:自定义一个方法 开一个新列 分为0和9

def fun(x):
    if x['rn'] ==1 or x['rn1']==1:
        return 0
    else:
        return 9
df['xin'] = df.apply(fun,axis=1)
df

 

第五步,拆表1 选值为9的行

第六步,拆表2 选值为0的行

 

第七步:  左连接两个表  为的是求中游的人 在历届有无获得最高分或者最低分

第八步: 保留控制,映射对应的列,去重,更名,排序

五,Pandas解答

import pandas as pd

def find_quiet_students(student: pd.DataFrame, exam: pd.DataFrame) -> pd.DataFrame:
    df = pd.merge(student,exam,on='student_id')  #合并表
    df = df.sort_values(['exam_id','score'],ascending=[True,False])  #排序  准备取最高分
    df['rn'] = df.groupby('exam_id')['score'].rank(method='dense',ascending=False)  #允许并列
    df = df.sort_values(['exam_id','score'],ascending=[True,True])  #排序 准备取最低分
    df['rn1'] = df.groupby('exam_id')['score'].rank(method='dense',ascending=True)  #允许并列
    def fun(x):
        if x['rn'] ==1 or x['rn1']==1:
            return 0
        else:
            return 9
    df['xin'] = df.apply(fun,axis=1)  #自定义函数 条件过滤
    df1 = df[df['xin']==9]  #拆表1
    df2 = df[df['xin']==0] #拆表2
    df3 = pd.merge(df1,df2,how='left',on='student_id') #左连接合并两个表
    df4 = df3[df3.isnull().any(axis=1)]  #保留nan值的行 
    df5 = df4[['student_id','student_name_x']]  #取两列
    df6 = df5.drop_duplicates()  #去重
    df7 =df6.rename(columns={"student_name_x":'student_name'})  #更名
    df8 = df7.sort_values('student_id',ascending=True)  #排序
    return df8 #返回

六,验证

七,知识点总结

  • Pandas 内连接的运用  API: merge
  • Pandas 分组排序的运用 允许并列
  • API:相当于sql中的 rank groupby....rank...method...ascending
  • Pandas 排序的运用 API:sort_values
  • Pandas 自定义函数的运用 API:apply  用作过滤
  • Pandas 左连接的运用 API:merge how left
  • Pandas 去重的运用 API : drop_duplicates()
  • Pandas更名的运用 API:rename
  • python函数的运用
  • 成绩处于中游的学生, 难点在于 每次测验都处于中游,且在历届测验中都没有获取过最高分和最低分

逻辑:

  • 先合并两个表 然后分别开窗 ---取最高值和最低值  考虑并列 所以用rank
  • 开一个新列 用作区分 待会儿方便拆2个表----
  • 左连接2个表 取我在本次测验是中游 以及在历次测验中都没有获取最高分和最低分过
  • 最后保留NAN值的行 和去重 以及更名,还有排序
  • 最后输出

  • 学习:知识的初次邂逅
  • 复习:知识的温故知新
  • 练习:知识的实践应用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值