Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

路径匹配只成功输出部分结果,很多路径点没有输出路径 #38

Open
chenwest95 opened this issue Feb 25, 2025 · 11 comments

Comments

@chenwest95
Copy link

我使用了create_node_from_link来对已有的路网文件(利用osmnx下载的openstreet路网)进行再生产,然后再路径匹配的时候,发现很多点都没有匹配成功,返回的res数量远远少于应返回的数量,图上面点是chunk(多辆车 20000条数据的df)可视化的点 高亮的线是匹配成功的线
new_link_gdf, new_node_gdf, node_group_status_gdf = ng.NetReverse.create_node_from_link(link_gdf=edges,
using_from_to=False,
update_link_field_list=['link_id',
'from_node',
'to_node',
'length'],
plain_crs='EPSG:32651',
modify_minimum_buffer=0.7,
ignore_dir=True,
execute_modify=True,
ignore_merge_rule=True,
out_fldr=r'./create_node/')
mpm = MapMatch(net=my_net, flag_name='xa_sample', # 指定项目名称xa_sample
use_sub_net=False, # 启用子网络
gps_buffer=200, top_k=30, # GPS点空间关联半径取100米,选取GPS点100米范围内最近的20个路段作为候选路段
dense_gps=False, # 不增密GPS点
use_heading_inf=False, omitted_l=6.0, # 启用GPS航向角矫正,若前后点GPS距离<=6米,将忽略航向角的修正
del_dwell=True, dwell_l_length=50.0, dwell_n=0, # 停留点删除参数
export_html=True, export_geo_res=True, use_gps_source=True, # 输出设置参数
gps_radius=15.0, export_all_agents=False, # 输出设置参数
out_fldr=r'./match')
res, warn_info, error_info = mpm.execute(gps_df=chunk) chunk是轨迹点的df 有字段agent_id time x y

Image

@zdsjjtTLG
Copy link
Owner

你应该单拎几条没匹配上的轨迹出来,然后看看他们输出的HTML文件,我才能帮你判断问题,你发个如此宏观的图,谁能看得出来问题?

@zdsjjtTLG
Copy link
Owner

为啥你的create_node_from_link函数会有ignore_dir参数?

@zdsjjtTLG
Copy link
Owner

而且我也没看到你的my_net是由新的new_link_gdf, new_node_gdf构建的呀?问问题麻烦给足信息好吗,完整代码截图,匹配失败轨迹的HTML等........

@chenwest95
Copy link
Author

抱歉 我之前把那个html文件输出关了 我来重新组织一下问题

@chenwest95
Copy link
Author

抱歉,我刚才的表述还是不准确。我附上了我的完整代码,读取的csv文件太大 我设置了chunk循环读取,但为了查看信息 实际只读取了一次,我刚才描述我把html关掉了并不准确,实际上是我设置了输出export_html=True 但实际上还是只生成了geojson文件( error_info 显示的车牌号反而没有生成geojson文件,应该是只有匹配成功的才生成了geojson文件),在指定位置r'./data/output/match_visualization/xa_sample'里面 没有找到html文件

import geopandas as gpd
import pandas as pd
import os
from shapely.geometry import Point, LineString
from tqdm import tqdm
import numpy as npIMPO
from gotrackit.map.Net import Net
from gotrackit.MapMatch import MapMatch
from gotrackit.model.Para import ParaGrid
import gotrackit.netreverse.NetGen as ng

1. 读取点和线 shapefile 文件

nodes = gpd.read_file(r'./-GIS/nodes.shp') # 替换为实际路径
edges = gpd.read_file(r'./-GIS/edges.shp') # 替换为实际路径

def calculate_AB_BA(res, new_link_gdf):

# 1. 去重 res
res = res.drop_duplicates(subset=['agent_id', 'link_id', 'from_node', 'to_node'])

# 2. 合并 res 和 new_link_gdf,获取 'reversed', 'from_node', 'to_node'
res = res.merge(new_link_gdf[['link_id', 'reversed']], 
                on='link_id', how='left')

# 3. 初始化 AB 和 BA 列
res['AB'] = 0
res['BA'] = 0

# 4. 根据 reversed 和 from_node, to_node 判断 AB 和 BA
for idx, row in res.iterrows():
    #print(row)
    # 如果 'from_node' 和 'to_node' 顺序与 new_link_gdf 中的顺序相同
    if row['from_node'] == new_link_gdf.loc[new_link_gdf['link_id'] == row['link_id'], 'from_node'].values[0] and \
       row['to_node'] == new_link_gdf.loc[new_link_gdf['link_id'] == row['link_id'], 'to_node'].values[0]:
           res.loc[idx, 'AB'] = 1
    else:
        res.loc[idx, 'AB'] = 1

# 5. 按 link_id 分组,统计 AB 和 BA 的总和
result = res.groupby('link_id').agg({'AB': 'sum', 'BA': 'sum'}).reset_index()

return result

根据条件设置 'dir' 列

def set_direction(row):
if row['oneway'] == False:
return 0
elif row['oneway'] == True and row['reversed'] == 'True':
return -1
elif row['oneway'] == True and row['reversed'] == 'False':
return 1

应用该函数并创建 'dir' 列

edges['dir'] = edges.apply(set_direction, axis=1)

nodes['node_id'] = nodes['osmid']
edges['link_id'] = edges.index+100000
edges['from_node'] = edges['u']
edges['to_node'] = edges['v']

确保 nodes 和 edges 的 CRS 一致

if nodes.crs != edges.crs:
edges = edges.to_crs(nodes.crs)

2. 准备路网数据

创建一个字典,将 osmid 映射到点 geometry

node_dict = dict(zip(nodes['osmid'], nodes.geometry))

为 edges 添加 from_point 和 to_point 列

edges['from_point'] = edges['u'].map(node_dict)
edges['to_point'] = edges['v'].map(node_dict)

new_link_gdf, new_node_gdf, node_group_status_gdf = ng.NetReverse.create_node_from_link(link_gdf=edges,
using_from_to=False,
update_link_field_list=['link_id',
'from_node',
'to_node',
'length'],
plain_crs='EPSG:32651',
modify_minimum_buffer=0.7,
execute_modify=True,
ignore_merge_rule=True,
out_fldr=r'./create_node/')

my_net = Net(link_gdf=new_link_gdf, node_gdf= new_node_gdf,
fmm_cache=True, recalc_cache=False, fmm_cache_fldr=r'./net/')

my_net.init_net() # net初始化
#新建一个网格参数对象
# 指定参数的取值范围列表, 可指定四个参数列表
pgd = ParaGrid(use_heading_inf_list=[False, True], beta_list=[0.1, 1.0], gps_sigma_list=[1.0, 5.0])

3. 读取 CSV 文件夹中的所有 CSV 文件

csv_folder = r'./02C范围内轨迹/' # 替换为实际路径
output_folder = r'./03路段流量/' # 替换为实际路径
os.makedirs(output_folder, exist_ok=True)

csv_files = [f for f in os.listdir(csv_folder) if f.endswith('.csv')]

逐个文件处理

for csv_file in tqdm(csv_files, desc="Processing CSV files"):
csv_path = os.path.join(csv_folder, csv_file)
output_shp_path = os.path.join(output_folder, os.path.splitext(csv_file)[0] + '.shp')

# 初始化统计字典
edge_counts = {edge_id: {'AB': 0, 'BA': 0} for edge_id in edges.index}
count = 0

# 4. 使用 chunksize 分块读取 CSV 文件
chunk_size = 50000  # 设定每次读取的行数,可以根据内存调整
chunks = pd.read_csv(csv_path, chunksize=chunk_size, parse_dates=['time'], infer_datetime_format=True)

outfile = output_folder + csv_file
results_list = []

# 逐块处理 CSV 文件
for chunk in chunks:
    count = count+chunk_size
    chunk = chunk[chunk['speed']>0]
    
    chunk['agent_id']=chunk['vehDID']
    chunk['lng']=chunk['x']
    chunk['lat']=chunk['y']
    
    mpm = MapMatch(net=my_net, flag_name='xa_sample', # 指定项目名称xa_sample
                   use_sub_net=False, # 启用子网络
                   gps_buffer=200, top_k=30, # GPS点空间关联半径取100米,选取GPS点100米范围内最近的20个路段作为候选路段
                   dense_gps=False, # 不增密GPS点
                   use_heading_inf=False, omitted_l=6.0,  # 启用GPS航向角矫正,若前后点GPS距离<=6米,将忽略航向角的修正
                   del_dwell=True, dwell_l_length=50.0, dwell_n=0,  # 停留点删除参数
                   export_html=True, export_geo_res=True, use_gps_source=True,  # 输出设置参数
                   gps_radius=15.0, export_all_agents=True, # 输出设置参数
                   out_fldr=r'./data/output/match_visualization/xa_sample')
    res, warn_info, error_info = mpm.execute(gps_df=chunk)
    
    
    res.to_csv(r'./match/match_res.csv', encoding='utf_8_sig', index=False)
    
    if len(res)>0:   
        resdf = calculate_AB_BA(res, new_link_gdf)     
        results_list.append(resdf)
        
        
    outdf = pd.concat(results_list, ignore_index=True)
    outdf = outdf.groupby('link_id').agg({'AB': 'sum', 'BA': 'sum'}).reset_index()
    
    outchunk = r'./match/chunk.csv'
    outchunkLK = r'./match/chunkLK.csv'
    chunk.to_csv(outchunk,encoding='gbk')
    outdf.to_csv(outchunkLK,encoding='gbk')
    
    
    break
break

Image

@zdsjjtTLG
Copy link
Owner

你试试别用网格参数ParaGrid,网格参数启用后会把警告信息都屏蔽掉,得看看输出了什么警告信息,估计有的库没安装对

@zdsjjtTLG
Copy link
Owner

控制台是否输出了“HTML输出失败?”

@chenwest95
Copy link
Author

可是我好像并没有使用ParaGrid,刚才给出的这个全段代码里面 只是在前面定义了一下网格,在MapMatch实例化的时候 并没有提及use_para_grid para_grid 两个参数,我重新在这里增加了一行,两个use_para_grid=False, para_grid=None,但是在文件夹里面还是没有html文件 控制台有报错TypeError('One of the arguments is of incorrect type. Please provide only Geometry objects.')
输出HTML可视化文件, 出现某些错误, 输出失败...

@zdsjjtTLG
Copy link
Owner

那就是因为库环境不对,这个可能是kepler的问题,之前有人遇到了,最好重新配一下环境。另外那些没匹配上的,你也可以看geojson文件,那些轨迹周围(buffer范围内)你看看是不是没有路网?或者路网缺失比较严重?或者路网行车方向不对?

@chenwest95
Copy link
Author

好的好的 谢谢 我再检查一下

@zdsjjtTLG
Copy link
Owner

路网没问题的话,匹配肯定没问题的,实在解决不了,加小助手微信,他帮你远程排查下

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants