力扣 Pandas 挑战(5)---数据分组

发布于:2025-08-01 ⋅ 阅读:(10) ⋅ 点赞:(0)

本文围绕力扣的Pandas简单题集,解析如何用Pandas完成基础数据处理任务,适合Pandas初学者学习。

题目1:1741. 查找每个员工花费的总时间

题目描述:

表: Employees

+-------------+------+
| Column Name | Type |
+-------------+------+
| emp_id      | int  |
| event_day   | date |
| in_time     | int  |
| out_time    | int  |
+-------------+------+
在 SQL 中,(emp_id, event_day, in_time) 是这个表的主键。
该表显示了员工在办公室的出入情况。
event_day 是此事件发生的日期,in_time 是员工进入办公室的时间,而 out_time 是他们离开办公室的时间。
in_time 和 out_time 的取值在1到1440之间。
题目保证同一天没有两个事件在时间上是相交的,并且保证 in_time 小于 out_time。

计算每位员工每天在办公室花费的总时间(以分钟为单位)。 请注意,在一天之内,同一员工是可以多次进入和离开办公室的。 在办公室里一次进出所花费的时间为out_time 减去 in_time。

返回结果表单的顺序无要求。

解题思路:

使用groupby()方法按event_day和emp_id进行分组,再将分组内的out_time减去in_time进行求和。

题目代码:

import pandas as pd

def total_time(employees: pd.DataFrame) -> pd.DataFrame:    
    #总共的时间等于出去的时间减去进来的时间
    employees["total_time"] = employees["out_time"] - employees["in_time"]
    #按event_day和emp_id两个列进行分组,对每个分组中的total_time进行求和,重置索引
    employees = employees.groupby(["event_day", "emp_id"])["total_time"].sum().reset_index()
    #修改列名
    employees.rename({"event_day": "day"}, axis=1, inplace=True)
    #将day数据类型转换为字符串类型
    employees["day"] = employees["day"].astype(str)
    return employees

题目2:511. 游戏玩法分析 I

题目描述:

活动表 Activity:

+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| player_id    | int     |
| device_id    | int     |
| event_date   | date    |
| games_played | int     |
+--------------+---------+
在 SQL 中,表的主键是 (player_id, event_date)。这张表展示了一些游戏玩家在游戏平台上的行为活动。每行数据记录了一名玩家在退出平台之前,当天使用同一台设备登录平台后打开的游戏的数目(可能是 0 个)。

查询每位玩家 第一次登录平台的日期。

查询结果的格式如下所示:

Activity 表:
+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 1         | 2         | 2016-03-01 | 5            |
| 1         | 2         | 2016-05-02 | 6            |
| 2         | 3         | 2017-06-25 | 1            |
| 3         | 1         | 2016-03-02 | 0            |
| 3         | 4         | 2018-07-03 | 5            |
+-----------+-----------+------------+--------------+

Result 表:
+-----------+-------------+
| player_id | first_login |
+-----------+-------------+
| 1         | 2016-03-01  |
| 2         | 2017-06-25  |
| 3         | 2016-03-02  |
+-----------+-------------+

解题思路:

按player_id分组,找出nvent_date中最小的日期。

题目代码:

import pandas as pd

def game_analysis(activity: pd.DataFrame) -> pd.DataFrame:
    df = activity.groupby('player_id')['event_date'].min().reset_index()

    return df.rename(columns = {'event_date':'first_login'})

题目3:2356. 每位教师所教授的科目种类的数量

题目描述:

表: Teacher

+-------------+------+
| Column Name | Type |
+-------------+------+
| teacher_id  | int  |
| subject_id  | int  |
| dept_id     | int  |
+-------------+------+
在 SQL 中,(subject_id, dept_id) 是该表的主键。
该表中的每一行都表示带有 teacher_id 的教师在系 dept_id 中教授科目 subject_id。

查询每位老师在大学里教授的科目种类的数量。

以 任意顺序 返回结果表。

解题思路:

使用groupby()方法按teacher_id分组并使用nuique()计算每组不同的subject_id数量。

题目代码:

import pandas as pd
def count_unique_subjects(teacher: pd.DataFrame) -> pd.DataFrame:
    #按teacher_id分组并计算每组不同的subject_id数量
    result = teacher.groupby('teacher_id')['subject_id'].nunique().reset_index()
    result.columns = ['teacher_id', 'cnt']

    return result

题目4:596. 超过 5 名学生的课

题目描述:

表: Courses

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| student     | varchar |
| class       | varchar |
+-------------+---------+
(student, class)是该表的主键(不同值的列的组合)。
该表的每一行表示学生的名字和他们注册的班级。

查询 至少有 5 个学生 的所有班级。

以 任意顺序 返回结果表。

解题思路:

按班级分开,计算每个班级对应学生的数量,筛选出有五个以上的班级,将班级列作为返回值返回。

题目代码:

import pandas as pd
def find_classes(courses: pd.DataFrame) -> pd.DataFrame:
    #按class分开并计算class对应的不同student的数量,重置索引并筛选条件
    result = courses.groupby('class')['student'].nunique().reset_index().query('student>=5')

    result=result.rename(columns={'student': 'student_count'})
    return result[['class']]

题目5:586. 订单最多的客户

题目描述:

表: Orders

+-----------------+----------+
| Column Name     | Type     |
+-----------------+----------+
| order_number    | int      |
| customer_number | int      |
+-----------------+----------+
在 SQL 中,Order_number是该表的主键。
此表包含关于订单ID和客户ID的信息。

查找下了 最多订单 的客户的 customer_number 。

测试用例生成后, 恰好有一个客户 比任何其他客户下了更多的订单。

查询结果格式如下所示。

示例 1:

输入: 
Orders 表:
+--------------+-----------------+
| order_number | customer_number |
+--------------+-----------------+
| 1            | 1               |
| 2            | 2               |
| 3            | 3               |
| 4            | 3               |
+--------------+-----------------+
输出: 
+-----------------+
| customer_number |
+-----------------+
| 3               |
+-----------------+
解释: 
customer_number 为 '3' 的顾客有两个订单,比顾客 '1' 或者 '2' 都要多,因为他们只有一个订单。
所以结果是该顾客的 customer_number ,也就是 3 。

解题思路:

方法1:计算每个客户的订单数量,再按数量降序排列,题目确定有且仅有一个最多的客户,以第一行数据作为返回值返回。提交时空值报错,还需要判断数据是否为空。

方法2:计算每个客户的订单数量,找到最大的一行作为返回值返回。与方法1相比,由于没有使用排序以及指定第一行数据,所以不需判断数据是否为空。

题目代码:

方法1:

import pandas as pd
def largest_orders(orders: pd.DataFrame) -> pd.DataFrame:
    # 计算每个客户的订单数量
    customer_counts = orders['customer_number'].value_counts().reset_index()
    customer_counts.columns = ['customer_number', 'order_count']

    #判断是否有数据
    if not customer_counts.empty:
        #降序
        customer_counts = customer_counts.sort_values('order_count', ascending=False)
        #题目保证有且只有一个。降序之后获取第一个
        result = customer_counts.head(1)[['customer_number']]
        return result
    else:
        return pd.DataFrame(columns=['customer_number'])

方法2:

import pandas as pd

def largest_orders(orders: pd.DataFrame) -> pd.DataFrame:
    #计算每个客户的订单数量
    df = orders.groupby('customer_number')['order_number'].count().reset_index()
    # 找到最大值的一行
    df = df[df['order_number'] == df['order_number'].max()]

    return df[['customer_number']]

题目6:1484. 按日期分组销售产品

题目描述:

表 Activities:

+-------------+---------+
| 列名         | 类型    |
+-------------+---------+
| sell_date   | date    |
| product     | varchar |
+-------------+---------+
该表没有主键(具有唯一值的列)。它可能包含重复项。
此表的每一行都包含产品名称和在市场上销售的日期。

编写解决方案找出每个日期、销售的不同产品的数量及其名称。
每个日期的销售产品名称应按词典序排列。
返回按 sell_date 排序的结果表。

解题思路:

分组计算num_sold和products,最后合并为dataframe数据返回。

题目代码:

import pandas as pd
def categorize_products(activities: pd.DataFrame) -> pd.DataFrame:
    #分组,计算每组不同产品数量
    grouped = activities.groupby('sell_date')['product']
    num_sold = grouped.nunique()

    #去重、排序、连接
    products = grouped.apply(lambda x: ','.join(sorted(x.unique())))

    # 合并结果
    result = pd.DataFrame({
        'num_sold': num_sold,
        'products': products
    }).reset_index().sort_values('sell_date')

    return result

题目7:1693. 每天的领导和合伙人

题目描述:

表:DailySales

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| date_id     | date    |
| make_name   | varchar |
| lead_id     | int     |
| partner_id  | int     |
+-------------+---------+
该表没有主键(具有唯一值的列)。它可能包含重复项。
该表包含日期、产品的名称,以及售给的领导和合伙人的编号。
名称只包含小写英文字母。

对于每一个 date_id 和 make_name,找出 不同 的 lead_id 以及 不同 的 partner_id 的数量。

按 任意顺序 返回结果表。

解题思路:

使用groupby()方法对date_id和make_name进行分组,在计算每个组内lead_id和partner_id中不同数据数量,并使用agg()方法聚合,重命名之后返回dataframe数据作为返回值。

题目代码:

import pandas as pd

def daily_leads_and_partners(daily_sales: pd.DataFrame) -> pd.DataFrame:
    #使用groupby()分组,分别计算lead_id和partner_id中不同数据数量并使用agg聚合
    df = daily_sales.groupby(['date_id', 'make_name']).agg({
        'lead_id': 'nunique',
        'partner_id': 'nunique'
    }).reset_index()
    
    df = df.rename(columns={
        'lead_id': 'unique_leads',
        'partner_id': 'unique_partners'
    })
    return df

网站公告

今日签到

点亮在社区的每一天
去签到