最近要处理NGSIM数据提取一些跟车场景,在此记录,也希望有同样问题的同学能一起交流进步!
数据标签
首先,记录一下 NGSIM 数据集中各标签的详细解释(部分):
- Vehicle_ID: 车辆的唯一标识符。
- Frame_ID: 帧的唯一标识符。
- Total_Frames: 当前车辆在整个轨迹中总共出现的帧数。
- Global_Time: 当前帧的全球时间戳(单位为毫秒)。
- Local_X: 车辆在当前帧中的局部横坐标(单位为英尺)。
- Local_Y: 车辆在当前帧中的局部纵坐标(单位为英尺)。
- Global_X: 车辆在当前帧中的全球横坐标(单位为英尺)。
- Global_Y: 车辆在当前帧中的全球纵坐标(单位为英尺)。
- v_Length: 车辆的长度(单位为英尺)。
- v_Width: 车辆的宽度(单位为英尺)。
- v_Class: 车辆的类型(例如乘用车、卡车等)。
- v_Vel: 车辆的速度(单位为英尺/秒)。
- v_Acc: 车辆的加速度(单位为英尺/秒²)。
- Lane_ID: 车辆所在车道的标识符。
- Preceeding: 当前车辆前方车辆的唯一标识符(如果存在)。
- Following: 当前车辆后方车辆的唯一标识符(如果存在)。
- Space_Hdwy: 当前车辆与前方车辆的空间间距(单位为英尺)。-> 间距是指一辆车的前中心到前一辆车的前中心之间的距离。
- Time_Hdwy: 当前车辆与前方车辆的时间间距(单位为秒)。
所有数据来源于: NGSIM
数据处理
接着,处理数据,我看了网上的帖子应该不需要太复杂的软件,用python+pandas就可以。
数据集很大,在读取数据的时候建议只读取自己需要的列。什么全局坐标之类的就不用提取了,筛选车辆的类型。只保留自己需要的车辆类型,摩托车啥的都去掉到这一步,就可以开始提取跟驰事件了。提取的时候,可以参考以下步骤:
- 下载下来的数据这里有点问题,我第一次下的是杂乱的排在一起的,第二次竟然全都排列好了,不管这些;我们应该把相同车辆ID的数据放到一起,先把跟驰事件中的主车找出来,并通过不同的跟车场景来划分出场景。
- 由于车辆ID是可能重复的,也就是说,不同时间会给不同的车编上同一个序号。为了解决这个问题,我们通过对于Global Time排序解决问题,具体做法就是对于每个车辆的ID分别做操作,在集合内部对于Global Time排序,进而得到统一的粗略行车轨迹了。
- 数据集内大多数车辆都会有换道的行为。经过2步骤以后需要把换道的部分和不同车辆的行驶数据区分开。解决方案:数据集内有自车数据和前车的id,所以当本车和前车id与上一时刻一致,车道信息与上一时刻一致,且全局时间按0.1秒增长,就认为跟驰行为是稳定的,没有换道产生。
- 由于我要做的是长时间持续的场景排查,所以要排除持续时间短于 30 秒的场景,即 10Hz 采样频率下的 300 帧。
代码如下:
安装python的库:
pip install pandas
第一步的代码:
"""第一步:先过滤掉摩托车和卡车,只留下automobile"""
import pandas as pd
# 假设您的数据保存在名为 'ngsim_data.csv' 的文件中
file_path = 'yourfilepath'
# 读取CSV文件到DataFrame中
df = pd.read_csv(file_path)
# 过滤v_Class为2的数据
filtered_df = df[df['v_Class'] == 2]
# 将过滤后的数据保存到新的CSV文件中
filtered_df.to_csv('yourfilepath', index=False)
第二步的代码:
"""第二步:通过Global_Time来进行升序排列"""
import pandas as pd
# 假设您的数据保存在名为 'ngsim_data.csv' 的文件中
file_path = 'yourpathfile'
# 读取CSV文件到DataFrame中
df = pd.read_csv(file_path)
# 对整个数据文件按Vehicle_ID和Global_Time进行升序排列
df_sorted = df.sort_values(by=['Vehicle_ID', 'Global_Time'])
# 将排序后的数据保存到新的CSV文件中
df_sorted.to_csv('yourpathfile', index=False)
# 输出前几行以确认
print("通过Global_Time来进行升序排列了")
第三、四步代码:
import pandas as pd
# 创建一个空的DataFrame用于保存最终结果
finally_data = pd.DataFrame()
# 读取CSV文件到DataFrame中
file_path = 'yourpathfile'
data = pd.read_csv(file_path)
# 对于每个唯一的Vehicle_ID
for ID in set(data.Vehicle_ID):
# 过滤出相同Vehicle_ID的数据,并按Global_Time升序排序
new_data = data[data.Vehicle_ID == ID].sort_values(by='Global_Time')
# 获取同一ID数据的Global_Time列表
lst_Global_Time = list(new_data.loc[:, 'Global_Time'])
lst_Lane_ID = list(new_data.loc[:, 'Lane_ID'])
lst_Preceding = list(new_data.loc[:, 'Preceeding'])
lst_c = []
lst_c.append(0)
# 获取切割索引列表
for i in range(len(new_data) - 1):
# 检查是否满足稳定跟车条件
if (lst_Global_Time[i + 1] - lst_Global_Time[i] != 100 or
lst_Lane_ID[i + 1] != lst_Lane_ID[i] or
lst_Preceding[i + 1] != lst_Preceding[i]):
lst_c.append(i + 1)
lst_c.append(len(lst_Global_Time))
# 切割并处理同一ID对应的不同片段
for j in range(len(lst_c) - 1):
S_S_data = new_data.iloc[lst_c[j]:lst_c[j + 1]].copy()
# 如果切割后数据长度大于1,则表示存在跟车行为
if len(S_S_data) > 1:
finally_data = pd.concat([finally_data, S_S_data])
# 清空切割索引列表,为下一个Vehicle_ID做准备
lst_c.clear()
# 排除持续时间短于30秒的场景(10Hz采样频率下少于300帧的片段)(如果不需要的可以删除这一部分)
min_duration_frames = 300
filtered_finally_data = finally_data.groupby('Vehicle_ID').filter(lambda x: len(x) >= min_duration_frames)
# 输出满足跟车条件且持续时间大于30秒的车辆总数
print(f'共有{len(filtered_finally_data["Vehicle_ID"].unique())}辆车辆进行了持续时间超过30秒的稳定跟车行为')
# 将最终结果保存到CSV文件中
filtered_finally_data.to_csv('yourpathfile', index=False)
print("ok")