我有一个可以使用任何编程语言完成的作业。我选择了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与汽车的三种不同关系:
- 后部 - 位于汽车后部(
cars.end > trucks.end
)
- 对面 - 是在汽车的对面(
cars.start >= trucks.start and cars.end <= trucks.end
)
- 前面 - 它位于汽车前面(
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(使用前将#替换为@)