[每日一练]排名靠前的旅行者

该题目来源于力扣的pandas题库,链接如下:

1407. 排名靠前的旅行者 - 力扣(LeetCode)

——题目要求:

表:Users

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| name          | varchar |
+---------------+---------+
id 是该表中具有唯一值的列。
name 是用户名字。

表:Rides

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| user_id       | int     |
| distance      | int     |
+---------------+---------+
id 是该表中具有唯一值的列。
user_id 是本次行程的用户的 id, 而该用户此次行程距离为 distance 。

编写解决方案,报告每个用户的旅行距离。

返回的结果表单,以 travelled_distance 降序排列 ,如果有两个或者更多的用户旅行了相同的距离, 那么再以 name 升序排列 。

返回结果格式如下例所示。

示例 1:

输入:
Users 表:
+------+-----------+
| id   | name      |
+------+-----------+
| 1    | Alice     |
| 2    | Bob       |
| 3    | Alex      |
| 4    | Donald    |
| 7    | Lee       |
| 13   | Jonathan  |
| 19   | Elvis     |
+------+-----------+

Rides 表:
+------+----------+----------+
| id   | user_id  | distance |
+------+----------+----------+
| 1    | 1        | 120      |
| 2    | 2        | 317      |
| 3    | 3        | 222      |
| 4    | 7        | 100      |
| 5    | 13       | 312      |
| 6    | 19       | 50       |
| 7    | 7        | 120      |
| 8    | 19       | 400      |
| 9    | 7        | 230      |
+------+----------+----------+
输出:
+----------+--------------------+
| name     | travelled_distance |
+----------+--------------------+
| Elvis    | 450                |
| Lee      | 450                |
| Bob      | 317                |
| Jonathan | 312                |
| Alex     | 222                |
| Alice    | 120                |
| Donald   | 0                  |
+----------+--------------------+
解释:
Elvis 和 Lee 旅行了 450 英里,Elvis 是排名靠前的旅行者,因为他的名字在字母表上的排序比 Lee 更小。
Bob, Jonathan, Alex 和 Alice 只有一次行程,我们只按此次行程的全部距离对他们排序。
Donald 没有任何行程, 他的旅行距离为 0。

——思路流程:

首先将Rides表进行里程数的分组求和,然后进行左右合并,之后进行里程数和名字的升序排序。

——代码实现:

import pandas as pd

def top_travellers(users: pd.DataFrame, rides: pd.DataFrame) -> pd.DataFrame:
    # 计算每个用户的旅行距离。提前进行排序,后续合并后数据变的复杂,再求和容易出错
    rides= rides.groupby('user_id')['distance'].sum().reset_index()

    # 将用户的旅行距离与用户信息合并。由于这里users的id对应rides的user_id,用左右连接。
    # 填充空值防止后续排序报错
    result_df = pd.merge(users, rides, left_on='id', right_on='user_id', how='left').fillna(0)

    # 重命名列名
    result_df.rename(columns={'distance': 'travelled_distance'}, inplace=True)

    # 按 travelled_distance 降序排列 ,如果有两个或者更多的用户旅行了相同的距离, 那么再以 name 升序排列。在切片中,先排序第一个元素,当第一个元素排序完成后,再考虑第二个元素的排序。
    result_df = result_df.sort_values(by=['travelled_distance', 'name'], ascending=[False, True])
    return result_df[['name','travelled_distance']]

——关于.sum()和.transform('sum')后缀形式的区别:

---.sum()形式:

  • .sum():这是一个聚合函数,当应用在DataFrame的列上时,它会对整个列的数值进行求和,返回一个标量值(单个值)。如果你使用data.groupby('name')['distance'].sum(),它会返回每个用户的旅行距离之和,而不会保留原始的行-用户映射关系。

---.transform('sum')形式:

  • 这是一个转换函数,当应用在DataFrame的列上时,它会对每个分组的数值进行操作,并返回一个与原始DataFrame相同大小的序列。如果你使用data.groupby('name')['distance'].transform('sum'),它会返回一个包含每个用户的旅行距离之和的序列,并且会根据原始的行-用户映射关系进行填充。

---代码解释:

import pandas as pd

# 创建示例数据
data = {
    'name': ['Alice', 'Bob', 'Alice', 'Bob', 'Alice'],
    'distance': [10, 20, 30, 40, 50]
}

df = pd.DataFrame(data)

# 使用 .sum() 对整个列进行求和
total_distance_sum = df['distance'].sum()
print("Total distance sum using .sum():", total_distance_sum)

# 使用 .groupby().transform('sum') 对每个分组的数值进行求和
grouped_distance_sum = df.groupby('name')['distance'].transform('sum')
print("Grouped distance sum using transform('sum'):\n", grouped_distance_sum)
'''
Total distance sum using .sum(): 150
Grouped distance sum using transform('sum'):
 0    90
1    60
2    90
3    60
4    90
Name: distance, dtype: int64
'''

可见单个.sum返回一个标量,而transform返回点对点的聚合数据。

  • 23
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值