다차로 하이패스 분석 코드 공부 1-1 전처리 (完) 20210526
목적
다차로 하이패스에서 장비를 설치하여 취득한 데이터(아마도 레이더장비를 통해 얻은 것 같다)로 위험지점을 찾아낸다
0. 패키지 준비
아나콘다 주피터넛븤에 판다스는 있으나 tqdm이 없으므로 먼저 깔아줍시다
뭐하는 패키지인지 모름
import도 고고
아 그리고 깔때 보안망이면 trusted-host 해줘야함 참고하세용
%pip install --trusted-host=pypi.python.org --trusted-host=pypi.org --trusted-host=files.pythonhosted.org tqdm import pandas as pd import os import gc from tqdm import tqdm
1. 데이터셋 준비
데이터를 저장할 곳과 불러올 것을 위해 변수에 각각 이름 저장
TempFolder는 파이썬상에서 만들 수 있는거 같은데 귀찮으니까 그냥 손으로 만듭시다
제발 한국인이면 맨유 응원합시다
curDir = os.getcwd() print(curDir) TempFolder = '_dataset' Filename = 'dataset_raw.xlsx' Filename_1 = TempFolder + '\dataset_1-1.csv' dataset_0 = pd.read_excel(Filename)
raw data를 보니 SCAN 별로 비어있는 행이 삽입되어있어 결측치제거로 없앤다
또한, 불러진 파일(read_excel은 DataFrame형태로 가져오는 것 같다)을 csv로 저장
저장할때 index를 살리고 싶으면 살려도 되지만 필요없음
그다음 메모리 정리
dataset_1 = dataset_0.dropna(axis=0) dataset_1.to_csv(Filename_1,index=False) # index를 True로 하면 공백의 column name 과 range(1:len(data))이 생김 del dataset_0, dataset_1 gc.collect()
2. 중복ID 정리
만들어진 데이터로 두번째 데이터 처리,
rename은 dic형태로 인풋을 받는데, 왜바꿧느냐 컬럼네임에 빈칸이 있어서 저렇게 다시 바꿔줌
dataset_4의 의미를 전혀 모르겠다
(조건문).cumsum() 이라는 문법도 처음본다 나 이런게 몰라하네
여기서 부터는 좀더 공부해서 다시 작성할 것
dataset_5 의 ~ 는 not의 의미!
Filename_2 = TempFolder + '\dataset_1-2.csv' dataset_0 = pd.read_csv(Filename_1) dataset_2 = dataset_0.copy() dataset_2.rename(columns = {dataset_2.columns[1]:'ID', dataset_2.columns[5]:'LANE'}, inplace=True) # 피벗 dataset_3 = dataset_2.pivot_table(index='SCAN', columns='ID', values='SPEED') dataset_4 = (dataset_3.isna() != dataset_3.isna().shift()).cumsum() dataset_5 = dataset_4[~dataset_3.isna()]
현재 SCAN이 인덱스로 가고 ID가 열로 하나씩 가있는데 여기에 melt를 사용하기 위해 reset_index() 활용
적용시 현재 index 즉 SCAN이 새로운 열로 붙게 되고 인덱스가 0: 로 새로 생김
여기에 melt를 적용
melt를 적용하면 다음과 같이 변경됨 / 또한 .dropna(axis=0)을 적용하여 결측치는 ㅂㅂ2
(before)
index SCAN ID0 ID1 ID2 ID3 0 0 1 2 3 4 1 1 5 6 7 8 (after) 모르고 인덱스 그리는거 까먹음 ㅈㅅ;;
SCAN ID tempID 0 ID0 1 0 ID1 2 0 ID2 3 1 ID2 7 1 ID3 8 apply 와 lambda의 기본적인 형태는
lambda 변수 : 변수를 포함한 함수 (변수란 하나의 값이 아닌 리스트형태로 가능한가보다) 이다.
기존ID와 tempID(cumsum을 한 결과값)을 합쳐(join함수) newID 생성 굳
210528 왜 cumsum을 했을까 생각해보니 SCAN 별로 ID가 랜덤으로 부여되는데 중복될수 있어서 그런듯
cumsum을 할 경우 같은 ID가 아닌것을 구분할 수 있다. 이걸 활용해 newID를 부여
dataset_6 = dataset_5.reset_index() # index 가 column으로 변함 dataset_7 = dataset_6.melt(id_vars = ['SCAN'], var_name = 'ID', value_name = 'tempID').dropna(axis = 0) dataset_7['newID'] = dataset_7[['ID', 'tempID']].astype(int).astype(str).apply(lambda x: '_'.join(x), axis=1) #df.변수.apply(함수) 함수에 변수를 넣은 결과값을 return함 #lambda 변수 : 변수를 포함한 함수
이제 merge를 사용해서 set_2 와 set_7을 합친다
merge에는 다양한 인수가 활용되는데 이번에 사용된 것만 보면
how='left' -> 왼쪽 자료(set_2)를 기준으로 붙인다
left_on = , right_on = -> 서로 비교할 기준을 설정해준다. 같으면 상관없는데 혹시나해서 넣어주신듯
필요없는 tempID는 .drop으로 날림
그리고 csv 저장 / 메모리 관리
.drop 중 axis=1 의 의미를 모르겠음
dataset_8 = pd.merge(dataset_2, dataset_7, how = 'left', left_on = ['SCAN', 'ID'], right_on = ['SCAN', 'ID']).drop(['tempID'], axis = 1) # pd.merge(df_left, df_right, how='inner', on=None) default 값 # 기준이 같으면 상관이 없지만 다를경우 left_on, right_on 으로 지정을 해줘야함 dataset_8.to_csv(Filename_2,index=False) del dataset_0, dataset_2, dataset_3, dataset_4, dataset_5, dataset_6, dataset_7, dataset_8 gc.collect()
3. 주행방향 차량 정보(속도, 가속도 등)
dataset_8 의 pivot을 통해 분석하려했으나, 램이 부족해서 실패,, 집 노트북으로 다시해야할듯,,
라고 생각했지만 박사님은 for문을 통해서 1000개 sample들을 여럿 생성하고 append 랑 concat 하심
메모리 사용하는건 똑같지 않을랑가?
또한 pivot value에 여러가지 넣으면 그냥 옆으로 변수 순서대로 붙는다고 생각하면됨
데이터가 너무 크니 201개만 해보겠다.
또한 현재의 속도, 가속도 등을 계산하기위해 SCAN의 직전값을 마련(shift(-1) / rename으로 구분
shift 사용시 인덱스(SCAN)는 안올라감을 명심하자
마지막으로 reset_index()를 통해 index였던 SCAN을 하나의 컬럼으로 집어넣는다
dataset_9 = dataset_8.iloc[0:200].pivot_table(index = 'SCAN', columns='newID', values=['XPOS', 'YPOS', 'SPEED']) dataset_10 = dataset_9.shift(-1).rename(columns = {'XPOS' : "XPOS_1", 'YPOS' : 'YPOS_1', 'SPEED':'SPEED_1'}) dataset_11 = dataset_10.reset_index() #index 였던 SCAN이 하나의 column으로 들어감
melt를 통해 다루기 쉬운 형태로 만들어주고,
column 중 이름이 NaN인것을 rename 해주고,
그 데이터로 피벗을 본다.
dataset_12 = pd.melt(dataset_11, id_vars = ['SCAN']) dataset_12.rename(columns = {dataset_12.columns[1] : 'VAR'}, inplace = True) # NaN column 명 바꿔주기 dataset_13 = dataset_12.pivot_table(index=["SCAN","newID"],columns=["VAR"],values='value') # 데이터셋의 이름을 명확히 해주는것이 좋다
이제 기존 데이터와 합쳐줄 차례이다.
기존 쉬프트 안한 dataset_8(중 일부, 201행)에 행 2개(SCAN, newID)를 index로 바꿔 만든뒤
쉬프트한 데이터를 .join()한다.
여기서 join은 merge와 같은 병합 개념이 아닌 단수 열추가이다.
마지막으로 가속도를 위해 eval 메쏘드를 사용하는데 이게 재밋다
변수 정의 및 추가를 한줄로 끝내버린다
나중에는 lambda 도 사용하도록,,
dataset_14 = dataset_8.iloc[0:200] # 가공전 데이터 dataset_15 = dataset_14.set_index(['SCAN',"newID"]) dataset_16 = dataset_15.join(dataset_13) # join은 병합이 아닌 단순 열추가입니다. dataset_16.eval(' ACC = ((SPEED_1-SPEED)/3.6)/(60/1000)', inplace = True)
4. 데이터 합치고 내보내기
이건 귀찮아서 그냥 넘기겠음
1. 사용할 데이터를 불러오고
2. 빈 리스트를 만들어주고
3. for문을 이용하여 잘라서 실행하고 append로 합쳐줌(append 는 단순 row 추가임)
* tqdm 은 진행상태를 텍스트형태의 bar로 알려줌
4. 결과값을 concat해주는데 concat 안에 리스트가 하나면 단순 데이터프레임화로 생각하면 되나?
5. result 출력
코드는 함수생성과 for문 돌리는 코드 두가지로 구분되는데 함수생성은 이전에 했던 과정을 함수화 시킨것(1~201행 가지고 놀았던것이라 그냥 생략하겠음)
filename_3 = TempFolder + '\\dataset_1-3_주행방향찾기.csv' dataset_0 = pd.read_csv(Filename_2) pivot_list = [] df_final = dataset_0 df_final_len = len(df_final) print(df_final_len) chunk_size = 1000 for i in tqdm(range(0, df_final_len, chunk_size)): """ i = 0 chunk_size = 1000 """ subDataset = df_final.iloc[i:i+chunk_size] # subDataset.info() subDirencionOfVehicle = FindDirectionOfVehicle(subDataset) pivot_list.append(subDirencionOfVehicle) dataset_2_result = pd.concat(pivot_list) dataset_2_result.to_csv(filename_3, index = False)
전처리 겨우 완료~~ 하기 싫다~~ 다음은 PET 테이블 작성인데 PET 가 뭐냐~~~~