使用 pandas 识别最近的物体

2024-04-16

我有一个可以使用任何编程语言完成的作业。我选择了Python和pandas,因为我几乎没有使用它们的经验,并且认为这将是一个很好的学习经历。我能够使用我从传统计算机编程中了解到的传统循环来完成作业,并且它在数千行上运行得很好,但是一旦我让它处理数百万行,它就会使我的笔记本电脑突然停止运行。任务概述如下。

在二维平面上有一条双车道的道路。一条车道供汽车使用,另一条车道供卡车使用。数据如下所示(每个表跨越数百万行):

cars

   id  start  end
0  C1    200  215
1  C2    110  125
2  C3    240  255
...

trucks

   id  start  end
0  T1    115  175
1  T2    200  260
2  T3    280  340
3  T4     25   85
...

上面的两个数据框对应于此:

start and end列代表道路上的任意位置,其中start= 车辆的后边缘并且end= 车辆的前缘。

任务是识别距离每辆车最近的卡车。卡车可以有up to与汽车的三种不同关系:

  1. 后部 - 位于汽车后部(cars.end > trucks.end)
  2. 对面 - 是在汽车的对面(cars.start >= trucks.start and cars.end <= trucks.end)
  3. 前面 - 它位于汽车前面(cars.start < trucks.start)

我强调“最多”是因为如果后面或前面有另一辆车距离最近的卡车更近,那么这种关系就会被忽略。在上图的情况下,我们可以观察到以下情况:

  • C1:后= T1,横向= T2,前=无(C3被阻挡)
  • C2:后= T4,横向=无,前= T1
  • C3:后=无(C1被阻挡),横向= T2,前= T3

最终输出需要附加到cars数据框以及以下新列:

  • 数据交叉引用自trucks数据框
  • 对于后面的位置,间隙距离(cars.start - trucks.end)
  • 对于前面的位置,间隙距离(trucks.start - cars.end)

决赛cars数据框应如下所示:

   id  start  end  back_id  back_start  back_end  back_distance  across_id  across_start  across_end  front_id  front_start  front_end  front_distance
0  C1    200  215       T1         115       175             25         T2           200         260
1  C2    110  125       T4          25        85             25                                             T1          115        175             -10
2  C3    240  255                                                       T2           200         260        T3          280        340              25

pandas 是完成这项任务的最佳工具吗?如果有一个更合适的工具,可以根据数百万行的某些计算有效地交叉引用和附加列,那么我会洗耳恭听。


所以对于 pandas,你可以使用merge_asof https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.merge_asof.html,这是一种方法,对于数百万行可能效率不高:

#first sort values
trucks = trucks.sort_values(['start'])
cars = cars.sort_values(['start'])

#create back condition
df_back = pd.merge_asof(trucks.rename(columns={col:f'back_{col}' 
                                               for col in trucks.columns}), 
                        cars.assign(back_end=lambda x: x['end']), 
                        on='back_end', direction='forward')\
            .query('end>back_end')\
            .assign(back_distance=lambda x: x['start']-x['back_end'])

#create across condition: here note that cars is the first of the 2 dataframes
df_across = pd.merge_asof(cars.assign(across_start=lambda x: x['start']),
                          trucks.rename(columns={col:f'across_{col}' 
                                                 for col in trucks.columns}), 
                          on=['across_start'], direction='backward')\
              .query('end<=across_end')

#create front condition
df_front = pd.merge_asof(trucks.rename(columns={col:f'front_{col}' 
                                                for col in trucks.columns}), 
                         cars.assign(front_start=lambda x: x['start']), 
                         on='front_start', direction='backward')\
             .query('start<front_start')\
             .assign(front_distance=lambda x: x['front_start']-x['end'])

# merge all back to cars
df_f = cars.merge(df_back, how='left')\
           .merge(df_across, how='left')\
           .merge(df_front, how='left')

你得到

print (df_f)
   id  start  end back_id  back_start  back_end  back_distance  across_start  \
0  C2    110  125      T4        25.0      85.0           25.0           NaN   
1  C1    200  215      T1       115.0     175.0           25.0         200.0   
2  C3    240  255     NaN         NaN       NaN            NaN         240.0   

  across_id  across_end front_id  front_start  front_end  front_distance  
0       NaN         NaN       T1        115.0      175.0           -10.0  
1        T2       260.0      NaN          NaN        NaN             NaN  
2        T2       260.0       T3        280.0      340.0            25.0  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 pandas 识别最近的物体 的相关文章

随机推荐