You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于条件使用Python Pandas编辑快递调度文件的条目顺序与内容

解决快递调度行程拆分的Pandas实现方案

你的需求核心是根据courier_status标记,将特定行程拆分为「原起点→快递起点→快递终点→原终点」的三段行程,同时重新生成每个用户的行程ID。这个场景用分组遍历的方式最直观可靠,也能适配你实际的多列大数据量情况,我给你一步步拆解实现:

核心思路

  1. 按id分组:每个用户的行程是独立序列,分组后处理不会互相干扰
  2. 遍历每组内的原始行程:
    • 普通行程(courier_status=False)直接保留,标记status='normal'
    • 需要绕行的行程(courier_status=True)拆分为3段:
      • 原起点→快递起点(status='courier')
      • 快递起点→快递终点(status='courier')
      • 快递终点→原终点(status='normal')
  3. 为每个用户的新行程重新生成连续的trip_id
  4. 合并所有分组结果得到最终调度表

完整代码实现

import pandas as pd

# 模拟你的原始数据(实际使用时替换成读取你的文件,比如pd.read_csv/Excel)
raw_data = {
    'id': [1,1,2,2,2],
    'trip_id': [1,2,1,2,3],
    'origin': ['A','B','F','G','H'],
    'destination': ['B','C','G','H','I'],
    'courier_status': [False, True, False, True, False],
    'package_origin': [None, 'X', None, 'Q', None],
    'package_destination': [None, 'Y', None, 'R', None]
}
df = pd.DataFrame(raw_data)

# 定义处理单用户行程分组的函数
def process_user_trips(group):
    new_trip_list = []
    # 遍历该用户的每一条原始行程
    for _, row in group.iterrows():
        if not row['courier_status']:
            # 普通行程直接添加
            new_trip_list.append({
                'id': row['id'],
                'origin': row['origin'],
                'destination': row['destination'],
                'status': 'normal'
                # 如果有其他列(比如时间、备注),直接在这里追加:'列名': row['列名']
            })
        else:
            # 拆分快递绕行行程
            # 1. 原起点→快递起点
            new_trip_list.append({
                'id': row['id'],
                'origin': row['origin'],
                'destination': row['package_origin'],
                'status': 'courier'
                # 其他列按需复制,比如'departure_time': row['departure_time']
            })
            # 2. 快递起点→快递终点
            new_trip_list.append({
                'id': row['id'],
                'origin': row['package_origin'],
                'destination': row['package_destination'],
                'status': 'courier'
                # 其他列按需复制
            })
            # 3. 快递终点→原终点
            new_trip_list.append({
                'id': row['id'],
                'origin': row['package_destination'],
                'destination': row['destination'],
                'status': 'normal'
                # 其他列按需复制
            })
    # 转换为DataFrame并生成连续的trip_id
    new_trips_df = pd.DataFrame(new_trip_list)
    new_trips_df['trip_id'] = new_trips_df.groupby('id').cumcount() + 1  # 每个用户从1开始计数
    # 调整列顺序和目标一致
    new_trips_df = new_trips_df[['id', 'trip_id', 'origin', 'destination', 'status']]
    return new_trips_df

# 应用分组处理并合并结果
newSchedule = df.groupby('id', group_keys=False).apply(process_user_trips).reset_index(drop=True)

# 查看最终结果
print(newSchedule)

代码运行结果

id  trip_id origin destination   status
0   1        1      A           B   normal
1   1        2      B           X  courier
2   1        3      X           Y  courier
3   1        4      Y           C   normal
4   2        1      F           G   normal
5   2        2      G           Q  courier
6   2        3      Q           R  courier
7   2        4      R           H   normal
8   2        5      H           I   normal

针对你的疑问的补充说明

  1. 关于你的原始思路:你之前想“新增行程追加后去重”的问题在于,原有的courier_status=True的行程是需要被替换掉的,而不是保留后追加,直接生成新行程列表的方式更准确,避免了去重逻辑的潜在错误。
  2. 循环vs np.where:np.where适合生成单行的条件列,但这里需要根据一行生成多行,所以分组+循环的方式更直观可控,而且代码可读性高,后续维护扩展也方便。
  3. 通用性适配:如果你的实际数据有更多列(比如出发时间、快递类型等),只需要在new_trip_list.append()的字典里添加对应的键值对即可,比如复制原行的列值,或者根据业务逻辑修改(比如快递行程的时间可以在原时间基础上调整)。

内容的提问来源于stack exchange,提问作者Ricky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 23:32:27