- 学习:知识的初次邂逅
- 复习:知识的温故知新
- 练习:知识的实践应用
目录
一,原题力扣链接
二,题干
表:
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值的行 和去重 以及更名,还有排序
- 最后输出
- 学习:知识的初次邂逅
- 复习:知识的温故知新
- 练习:知识的实践应用