Browse Source

rename : dir -> dire (four or eight directions is reperesented by the variable name 'dire' rather than 'dir')

master
김선중 2 years ago
parent
commit
9722d453f7
4 changed files with 621 additions and 797 deletions
  1. +16
    -0
      .vscode/launch.json
  2. +1
    -1
      Data/tables/nema.csv
  3. +564
    -681
      Results/sn_1704418800.add.xml
  4. +40
    -115
      Scripts/preprocess_daily.py

+ 16
- 0
.vscode/launch.json View File

@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File with Arguments",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"args": "${command:pickArgs}"
}
]
}

+ 1
- 1
Data/tables/nema.csv View File

@ -1,4 +1,4 @@
move_no,inc_dir,out_dir
move_no,inc_dire,out_dire
1,동,남
2,서,동
3,남,서

+ 564
- 681
Results/sn_1704418800.add.xml
File diff suppressed because it is too large
View File


+ 40
- 115
Scripts/preprocess_daily.py View File

@ -254,7 +254,7 @@ class DailyPreprocessor():
'''
match2의 각 이동류번호에 진입방향, 진출방향을 매칭시킨 테이블
컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir
컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dire, out_dire
'''
# nema 정보 불러오기 및 병합
self.match3 = pd.merge(self.match2, self.nema, how='left', on='move_no').drop_duplicates()
@ -264,7 +264,7 @@ class DailyPreprocessor():
'''
match3의 각 이동류번호에 진입, 진출 방위각을 매칭시킨 테이블
컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle
컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dire, out_dire, inc_angle, out_angle
'''
# # 계층화
@ -312,29 +312,10 @@ class DailyPreprocessor():
# 2-1-5
def make_match5(self):
'''
진입엣지id, 진출엣지id, 노드id를 추가함 (주교차로).
- match4의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle
- match5의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle, inc_edge, out_edge, node_id
사용된 데이터 :
(1) net
- 성남시 정자동 부근의 샘플 네트워크
(2) inter_node
- 교차로번호와 노드id를 매칭시키는 테이블.
- parent/child 정보도 포함되어 있음
- 컬럼 : inter_no, node_id, inter_type
(3) inter_info
- 교차로 정보. 여기에서는 위도와 경도가 쓰임.
- 컬럼 : inter_no, inter_name, inter_lat, inter_lon, group_no, main_phase_no
진입엣지id, 진출엣지id를 얻는 과정 :
- match5 = match4.copy()의 각 열을 순회하면서 아래 과정을 반복함.
* 진입에 대해서만 서술하겠지만 진출도 마찬가지로 설명될 수 있음
- 해당 행의 교차로정보로부터 노드ID를 얻어내고, 해당 노드에 대한 모든 진출엣지id를 inc_edges에 저장.
* inc_edge(진입엣지) : incoming edge, out_edge(진출엣지) : outgoing_edge
- inc_edges의 모든 진입엣지에 대하여 진입방향(inc_dires, 2차원 단위벡터)을 얻어냄.
- 해당 행의 진입각으로부터 그에 대응되는 진입각방향(단위벡터)를 얻어냄.
- 주어진 진입각방향에 대하여 내적이 가장 작은 진입방향에 대한 진입엣지를 inc_edge_id로 지정함.
match4의 각 행에 진입엣지id, 진출엣지id 노드id 추가한 테이블
* 진입, 진출엣지id를 얻은 방법 : cosine similarity
컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dire, out_dire, inc_angle, out_angle, inc_edge, out_edge, node_id
'''
# parent node만 가져옴.
@ -392,53 +373,9 @@ class DailyPreprocessor():
# 2-1-6
def make_match6(self):
'''
진입엣지id, 진출엣지id, 노드id를 추가함 (부교차로).
- match6의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle, inc_edge, out_edge, node_id
사용된 데이터 :
(1) inter_node
- 교차로번호와 노드id를 매칭시키는 테이블.
- parent/child 정보도 포함되어 있음
- 컬럼 : inter_no, node_id, inter_type
(2) uturn (유턴정보)
- 컬럼 : parent_id, child_id, direction, condition, inc_edge, out_edge
- parent_id, child_id : 주교차로id, 유턴교차로id
- direction : 주교차로에 대한 유턴노드의 상대적인 위치(방향)
- condition : 좌회전시, 직진시, 직좌시, 보행신호시 중 하나
- inc_edge, out_edge : 유턴에 대한 진입진출엣지
(3) coord (연동교차로정보)
- 컬럼 : parent_id, child_id, phase_no, ring_type, inc_edge, out_edge
- parent_id, child_id : 주교차로id, 연동교차로id
- 나머지 컬럼 : 각 (현시, 링)별 진입진출엣지
설명 :
- match5는 주교차로에 대해서만 진입엣지id, 진출엣지id, 노드id를 추가했었음.
여기에서 uturn, coord를 사용해서 부교차로들(유턴교차로, 연동교차로)에 대해서도 해당 값들을 부여함.
유턴교차로 :
- directions를 정북기준 시계방향의 8방위로 정함.
- 이를 통해 진입방향이 주어진 경우에 좌회전, 직진, 보행 등에 대한 (진입방향, 진출방향)을 얻어낼 수 있음.
- 예) 진입방향(direction)이 '북'일 때,
- 직진 : (북, 남)
* 남 : directions[(ind + 4) % len(directions)]
- 좌회전 : (북, 동)
* 동 : directions[(ind + 2) % len(directions)]
- 보행 : (서, 동)
* 서 : directions[(ind - 2) % len(directions)]
- uturn의 각 행을 순회하면서 아래 과정을 반복함
- match5에서 parent_id에 해당하는 행들을 가져옴(cmatch).
- condition 별로 진입방향, 진출방향을 정함.
- 상술한 directions를 활용하여 정함.
- (진입방향, 진출방향)을 고려하여 (현시, 링) 별로 진입엣지id, 진출엣지id를 정함.
- ex) cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]
- 순회하면서 만든 cmatch를 cmatchs라는 리스트에 저장함.
연동교차로 :
- 연동교차로의 경우 coord에 (현시, 링)별 진입엣지ID, 진출엣지ID가 명시되어 있음.
- 'inc_dir', 'out_dir', 'inc_angle','out_angle'와 같은 열들은 np.nan을 지정해놓음.
- 이 열들은, 사실상 다음 스텝부터는 사용되지 않는 열들이기 때문에 np.nan으로 지정해놓아도 문제없음.
match6 :
- 이렇게 얻은 match5, cmatchs, coord를 모두 pd.concat하여 match6을 얻어냄.
match5에서 부교차로(유턴교차로, 연동교차로)에 대한 행들을 추가함
컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dire, out_dire, inc_angle, out_angle, inc_edge, out_edge, node_id
'''
self.node2inter = dict(zip(self.inter_node['node_id'], self.inter_node['inter_no']))
@ -489,8 +426,8 @@ class DailyPreprocessor():
out_dire_right = self.directions[(ind + 2) % len(self.directions)]
# 보행신호시/좌회전시 조건
pedes_exists = (cmatch.inc_dir==inc_dire_pedes) & (cmatch.out_dir==out_dire_pedes)
right_exists = (cmatch.inc_dir==inc_dire_right) & (cmatch.out_dir==out_dire_right)
pedes_exists = (cmatch.inc_dire==inc_dire_pedes) & (cmatch.out_dire==out_dire_pedes)
right_exists = (cmatch.inc_dire==inc_dire_right) & (cmatch.out_dire==out_dire_right)
# 보행신호시/좌회전시 진입/진출 엣지id 배정
ind = self.directions.index(direction)
@ -515,18 +452,18 @@ class DailyPreprocessor():
cmatch.loc[pedes_exists, ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]
# 보행신호이동류(17) 발생시
elif crosswalk_on.any():
cmatch.loc[crosswalk_on & (cmatch.out_dir!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]
cmatch.loc[crosswalk_on & (cmatch.out_dire!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]
# 신호없음이동류(18) 발생시
elif all_redsigns.any():
cmatch.loc[all_redsigns & (cmatch.out_dir!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]
cmatch.loc[all_redsigns & (cmatch.out_dire!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]
cmatches.append(cmatch)
# 각 연등교차로(coordination node)에 대하여 (inc_edge_id, out_edge_id) 부여
self.coord['inter_no'] = self.coord['parent_id'].map(self.node2inter)
self.coord = self.coord.rename(columns={'child_id':'node_id'})
self.coord[['inc_dir', 'out_dir', 'inc_angle','out_angle']] = np.nan
self.coord[['inc_dire', 'out_dire', 'inc_angle','out_angle']] = np.nan
self.coord['move_no'] = 20
self.coord = self.coord[['inter_no', 'phase_no', 'ring_type', 'move_no', 'inc_dir', 'out_dir', 'inc_angle','out_angle', 'inc_edge_id', 'out_edge_id', 'node_id']]
self.coord = self.coord[['inter_no', 'phase_no', 'ring_type', 'move_no', 'inc_dire', 'out_dire', 'inc_angle','out_angle', 'inc_edge_id', 'out_edge_id', 'node_id']]
# display(coord)
cmatches = pd.concat(cmatches)
@ -537,50 +474,38 @@ class DailyPreprocessor():
# 2-1-7
def make_matching(self):
'''
이동류 매칭 : 각 교차로에 대하여, 가능한 모든 이동류 (1~18, 21)에 대한 진입·진출엣지ID를 지정한다.
모든 이동류에 대해 지정하므로, 시차제시 이전과 다른 이동류가 등장하더라도 항상 진입·진출 엣지 ID를 지정할 수 있다.
- matching의 컬럼 : inter_no, move_no, inc_dir, out_dir, inc_edge, out_edge, node_id
설명 :
- 필요한 리스트, 딕셔너리 등을 정의
(1) 가능한 (진입방향, 진출방향) 목록 [리스트]
(2) 각 교차로별 방향 목록 : pdires (possible directions) [딕셔너리]
(3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id) [딕셔너리]
(4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id) [딕셔너리]
(5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows) [딕셔너리]
- matching은 빈 리스트로 지정.
- 모든 노드id에 대하여 다음 과정을 반복
- 해당 노드id에 대한 모든 가능한 (진입방향, 진출방향)에 대하여 다음 과정을 반복
- (노드id, 진입방향)으로부터 진입엣지id를 얻어냄. 마찬가지로 진출엣지id도 얻어냄
- 얻어낸 정보를 바탕으로 한 행(new_row)을 만들고 이것을 matching에 append
각 교차로에 대하여, 가능한 모든 이동류 (1~18, 21)에 대한 진입·진출엣지ID를 지정한 테이블
* 시차제
컬럼명 : inter_no, move_no, inc_dire, out_dire, inc_edge, out_edge, node_id
'''
self.match7 = self.match6.copy()
self.match7 = self.match7[['inter_no', 'move_no', 'inc_dir', 'out_dir', 'inc_edge', 'out_edge', 'node_id']]
self.match7 = self.match7[['inter_no', 'move_no', 'inc_dire', 'out_dire', 'inc_edge', 'out_edge', 'node_id']]
# parent_ids = sorted(self.inter_node[self.inter_node.inter_type=='parent'].node_id.unique())
# child_ids = sorted(self.inter_node[self.inter_node.inter_type=='child'].node_id.unique())
# (1) 가능한 (진입방향, 진출방향) 목록
flows = self.nema.dropna().apply(lambda row: (row['inc_dir'], row['out_dir']), axis=1).tolist()
flows = self.nema.dropna().apply(lambda row: (row['inc_dire'], row['out_dire']), axis=1).tolist()
# (2) 각 교차로별 방향 목록 : pdires (possible directions)
pdires = {}
for node_id in self.parent_ids:
dires = self.match7[self.match7.node_id == node_id][['inc_dir','out_dir']].values.flatten()
dires = self.match7[self.match7.node_id == node_id][['inc_dire','out_dire']].values.flatten()
dires = {dire for dire in dires if type(dire)==str}
pdires[node_id] = dires
# (3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id)
inc2id = {}
for node_id in self.parent_ids:
for inc_dir in pdires[node_id]:
df = self.match7[(self.match7.node_id==node_id) & (self.match7.inc_dir==inc_dir)]
inc2id[(node_id, inc_dir)] = df.inc_edge.iloc[0]
for inc_dire in pdires[node_id]:
df = self.match7[(self.match7.node_id==node_id) & (self.match7.inc_dire==inc_dire)]
inc2id[(node_id, inc_dire)] = df.inc_edge.iloc[0]
# (4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id)
out2id = {}
for node_id in self.parent_ids:
for out_dir in pdires[node_id]:
df = self.match7[(self.match7.node_id==node_id) & (self.match7.out_dir==out_dir)]
out2id[(node_id, out_dir)] = df.out_edge.iloc[0]
for out_dire in pdires[node_id]:
df = self.match7[(self.match7.node_id==node_id) & (self.match7.out_dire==out_dire)]
out2id[(node_id, out_dire)] = df.out_edge.iloc[0]
# (5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows)
pflow = {}
for node_id in self.parent_ids:
@ -592,28 +517,28 @@ class DailyPreprocessor():
for node_id in self.parent_ids:
inter_no = self.node2inter[node_id]
# 좌회전과 직진(1 ~ 16)
for (inc_dir, out_dir) in pflow[node_id]:
move_no = self.nema[(self.nema.inc_dir==inc_dir) & (self.nema.out_dir==out_dir)].move_no.iloc[0]
inc_edge = inc2id[(node_id, inc_dir)]
out_edge = out2id[(node_id, out_dir)]
for (inc_dire, out_dire) in pflow[node_id]:
move_no = self.nema[(self.nema.inc_dire==inc_dire) & (self.nema.out_dire==out_dire)].move_no.iloc[0]
inc_edge = inc2id[(node_id, inc_dire)]
out_edge = out2id[(node_id, out_dire)]
new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[move_no],
'inc_dir':[inc_dir], 'out_dir':[out_dir],
'inc_dire':[inc_dire], 'out_dire':[out_dire],
'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})
self.matching.append(new_row)
# 보행신호(17), 전적색(18)
new_row = pd.DataFrame({'inter_no':[inter_no] * 2, 'move_no':[17, 18],
'inc_dir':[None]*2, 'out_dir':[None]*2,
'inc_dire':[None]*2, 'out_dire':[None]*2,
'inc_edge':[None]*2, 'out_edge':[None]*2, 'node_id':[node_id]*2})
self.matching.append(new_row)
# 신호우회전(21)
for d in range(len(dires_right)-1):
inc_dir = dires_right[d]
out_dir = dires_right[d+1]
if {inc_dir, out_dir}.issubset(pdires[node_id]):
inc_edge = inc2id[(node_id, inc_dir)]
out_edge = out2id[(node_id, out_dir)]
inc_dire = dires_right[d]
out_dire = dires_right[d+1]
if {inc_dire, out_dire}.issubset(pdires[node_id]):
inc_edge = inc2id[(node_id, inc_dire)]
out_edge = out2id[(node_id, out_dire)]
new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[21],
'inc_dir':[inc_dir], 'out_dir':[out_dir],
'inc_dire':[inc_dire], 'out_dire':[out_dire],
'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})
self.matching.append(new_row)
self.matching.append(self.match7[self.match7.node_id.isin(self.child_ids)])

Loading…
Cancel
Save