代码之家  ›  专栏  ›  技术社区  ›  Emac

python pandas根据条件创建运行“id”

  •  0
  • Emac  · 技术社区  · 6 年前

    我需要根据与前几行相关的特定条件为熊猫行创建一个唯一的“id”字段。

    下面是我的数据示例:

      current_driver customer_id    pu_actual_dt      service
    0        167       1214      2018-06-28 13:24:00    DED
    1        167       1214      2018-06-28 13:25:00    DED
    2        167       1214      2018-06-28 14:43:00    DED
    3        243       1214      2018-06-28 19:41:00    DED
    4        243       1214      2018-06-28 19:41:00    DED
    5        250       1214      2018-06-28 17:19:00    DED
    6        250       1214      2018-06-28 18:00:00    DED
    7        250       1214      2018-06-28 18:18:00    DED
    8        259       1214      2018-06-28 19:40:00    DED
    9        259       1214      2018-06-28 19:40:00    DED
    10       259       1214      2018-06-28 20:14:00    DED
    11       260       1214      2018-06-28 17:39:00    DED
    12       260       1214      2018-06-28 17:39:00    DED
    13       260       1214      2018-06-28 17:39:00    DED
    14       260       1214      2018-06-28 17:39:00    DED
    15       263       1214      2018-06-28 18:34:00    DED
    16       263       1214      2018-06-28 18:43:00    DED
    17       263       1214      2018-06-28 18:43:00    DED
    

    我需要做的是用以下逻辑创建另一个列:如果当前的_驱动程序与前一行的当前_驱动程序相同,并且客户ID与前一行的客户ID相同,并且pu_实际的_dt在前一行的半小时内,那么它应该都具有相同的ID。因此,对于前两行,但由于第三行的pu_actual_dt超过半小时,所以它的id为“2”。然后第四行有一个不同的驱动程序,因此该行的id为“3”,同时还有第5行,因为它与第4行有相同的驱动程序/客户id/pu实际dt。

    在我解释pu_actual_dt中的细微差异(请参见前两行)之前,我能够通过连接字段并在每次行与前一个连接不匹配时启动一个新的id来解决这个问题。例如,我用这个来创建id之前:

    df = df.assign(id=(df['route_concate']).astype('category').cat.codes)
    

    然而,当我在pu_-actual_dt上有微小的差异时,这种连接逻辑就不起作用。

    所以我试图通过这样做来解释时间的微小变化:

    df['id'] = np.where((df['current_driver'] == df['current_driver'].shift(1) ) 
    & (df['customer_id'] == df['customer_id'].shift(1)) 
    & (df['pu_actual_dt'] < df['pu_actual_dt'].shift(1) + pd.Timedelta(minutes=30)) 
    & (df['pu_actual_dt'] > df['pu_actual_dt'].shift(1) - pd.Timedelta(minutes=30)) 
    & (df['service'] == 'DED'), df['id'].shift(1), df['id'].shift(1) + 1)
    

    我在这里要做的是,对每一行来说,如果当前驱动程序=上一行的当前驱动程序,而客户id=上一行的客户id,则pu-actual-dt在前一行的pu-actual-dt之前或之后的30分钟内,并且service='ded',则使用前一行的id。如果没有,则在前一行的id中添加1。

    我不知道我做错了什么,但它正在返回一些非常不可预测的结果。有一次它从75号降到34号,然后又回到36号?

    有什么办法能更好地解决我的问题?(也就是id从“1”开始的一个)。谢谢你一如既往的帮助!

    1 回复  |  直到 6 年前
        1
  •  2
  •   Ben.T    6 年前

    你的 np.where 是一个好主意,但有一点不同:分配 1 如果不符合条件 None 如果符合以下条件:

    df['id'] = np.where((df['current_driver'] == df['current_driver'].shift(1) ) 
    & (df['customer_id'] == df['customer_id'].shift(1)) 
    & (df['pu_actual_dt'] < df['pu_actual_dt'].shift(1) + pd.Timedelta(minutes=30)) 
    & (df['pu_actual_dt'] > df['pu_actual_dt'].shift(1) - pd.Timedelta(minutes=30)) 
    & (df['service'] == 'DED'), None, 1) # NOTE the None and 1 here are explain above
    

    现在你有了 1个 要在中增加值的每一行 id ,所以使用 cumsum 我是说, ffill astype (对GE整数不浮动)例如:

    df['id'] = df['id'].cumsum().ffill().astype(int)
    

    举你的例子

        current_driver  customer_id        pu_actual_dt service  id
    0              167         1214 2018-06-28 13:24:00     DED   1
    1              167         1214 2018-06-28 13:25:00     DED   1
    2              167         1214 2018-06-28 14:43:00     DED   2
    3              243         1214 2018-06-28 19:41:00     DED   3
    4              243         1214 2018-06-28 19:41:00     DED   3
    5              250         1214 2018-06-28 17:19:00     DED   4
    6              250         1214 2018-06-28 18:00:00     DED   5
    7              250         1214 2018-06-28 18:18:00     DED   5
    8              259         1214 2018-06-28 19:40:00     DED   6
    9              259         1214 2018-06-28 19:40:00     DED   6
    10             259         1214 2018-06-28 20:14:00     DED   7
    11             260         1214 2018-06-28 17:39:00     DED   8
    12             260         1214 2018-06-28 17:39:00     DED   8
    13             260         1214 2018-06-28 17:39:00     DED   8
    14             260         1214 2018-06-28 17:39:00     DED   8
    15             263         1214 2018-06-28 18:34:00     DED   9
    16             263         1214 2018-06-28 18:43:00     DED   9
    17             263         1214 2018-06-28 18:43:00     DED   9