창원시 불법 주정차 단속 위반에 관한 파일을 전처리 하려고 한다.
## csv 파일 읽어오기 ##
# 파일 경로를 변수에 할당
path = 'illegal_parking(1).csv'
# open()함수를 사용하여 파일 열기 / 읽기전용('r')으로 읽어들여 변수에 할당
file = open(path, 'r')
# 불러온 파일을 readlines()함수를 사용하여 한 줄씩 문자열로 바꿔서 리스트로 반환
# 이 때 몇 번 줄부터 몇 번 줄까지 가져올지를 대괄호를 사용하여 정할 수 있다
lines = file.readlines()[1:5000]
# 열었던 파일은 반드시 닫기
file.close()
이렇게 불러온 파일은 썩 보기가 좋지 않다.
['2017-01-02,15:54,의창구,팔용동 숲속나라어린이집 주,현장단속\n',
'2017-01-02,16:08,의창구,중동 새마을금고 주변,현장단속\n',
'2017-01-02,16:09,의창구,중동 새마을금고 주변,현장단속\n',
'2017-01-02,16:10,의창구,중동 새마을금고 주변,현장단속\n',
...
문자열''
단위를 리스트로 만든 다음 다시 리스트 안에 넣어줄 것이다.
# *csv 파일을 python list(중첩 리스트) 자료형으로 만들기
list_data = []
# 문자열 하나하나를 순회
for i in lines:
# 불필요한 공백을 제거(strip메서드)하고 문자열 내의 콤마를 단위로 요소를 나눈다(split메서드)
temp = i.strip().split(',')
# 나눈 요소요소의 자료형은 문자열이고 이 요소들을 모아서 temp라는 리스트를 만든다
# 리스트 temp들을 리스트 안에 쌓아준다
list_data.append(temp)
여기까지 수행하면 중첩리스트가 완성되고 보기가 꽤 좋아진다.
[['2017-01-02', '15:54', '의창구', '팔용동 숲속나라어린이집 주', '현장단속'],
['2017-01-02', '16:08', '의창구', '중동 새마을금고 주변', '현장단속'],
['2017-01-02', '16:09', '의창구', '중동 새마을금고 주변', '현장단속'],
['2017-01-02', '16:10', '의창구', '중동 새마을금고 주변', '현장단속'],
['2017-01-02', '16:10', '의창구', '중동 새마을금고 주변', '현장단속'],
...
내가 다루려고 하는 칼럼은 '행정구'와 '위치'이다.
두 자료의 빈도를 구해서 주차 구역이 얼마나 부족한지를 예측해볼 것이므로...
따라서 인덱스2번과 인덱스3번 요소만 체크하여 횟수를 구할 것이다.
# 행정구 및 행정동 추출하기(인덱스 2~3)
data_set = []
for i in list_data:
temp = i[2:3+1]
data_set.append(temp)
# print(data_set)
리스트를 또다시 새로 만들었다.
행정구와 행정동의 카운트를 나누어서 해볼 생각이다.
행정구의 경우 'ㅇㅇ구'로 이름이 명확하다.
행정동은 이름이 중구난방이라 미리 딕셔너리를 만들어야겠다.
먼저 간단해보이는 행정구부터 카운트 해보겠다.
# 행정구 카운트하기
count_cat_list = []
count_cat_dict = {}
# 반복문을 돌면서 새로운 리스트에 행정구 이름을 하나씩 넣을 건데
for i in data_set:
# 리스트에 없는 행정구라면 중복확인을 위해 넣는다
# 그리고 딕셔너리에 행정구 이름과 횟수 값을 생성한다
if i[0] not in count_cat_list:
count_cat_list.append(i[0])
count_cat_dict[i[0]] = 1
# 만약 리스트 안에 행정구 이름이 있다면
if i[0] in count_list:
# 딕셔너리에서 해당 키의 값에 +1을 하여 횟수를 올린다
count_cat_dict[i[0]] += 1
print(count_cat_dict)
>>
{의창구:5000}
일단 의창구만 나오는 게 맞다. 대략 60만 줄 정도 되는 파일이기 때문이다.
다음은 행정동을 카운트해야 한다.
행정동 이름을 키값으로 하는 딕셔너리를 미리 만든다.
count_kitty_dict = {
"동읍":0, "북면":0, "대산":0, "의창":0, "팔룡":0, "팔용":0, "명곡":0, "봉림":0, "용호":0, "명서":0, "소답":0, "대원":0,
"반송":0, "중앙":0, "용지동":0, "상남":0, "사파":0, "가음":0, "성주":0, "웅남":0, "중동":0,
"구산":0, "진동":0, "진북":0, "진전":0, "현동":0, "가포":0, "월영":0, "문화동":0, "반월중앙":0, "반월 중앙":0,
"완월":0, "자산":0, "오동":0, "교방":0, "합포":0, "산호":0,
"회원1":0, "회원 1":0, "회원2":0, "회원 2":0, "석전":0, "회성":0, "양덕1":0, "양덕 1":0, "양덕2":0,"양덕 2":0,
"합성1":0, "합성 1":0, "합성2":0, "합성 2":0, "구암1":0, "구암 1":0, "구암2":0, "구암 2":0, "봉암":0,
"충무":0, "여좌":0, "태백":0, "경화":0, "병암":0, "석동":0, "이동":0, "자은":0, "덕산":0, "풍호":0,
"웅천":0, "웅동1":0, "웅동 1":0, "웅동2":0, "웅동 2":0
}
DITCTIONARY자료형.keys()
메서드를 사용하면
딕셔너리의 key만을 추출하여 리스트로 만들 수 있다
반복문을 돌리기에 LIST가 편리하기 때문에 만들어둔다
count_kitty_list = count_kitty_dict.keys()
count_kitty_list = [
'동읍', '북면', '대산', '의창', '팔룡', '팔용', '명곡', '봉림', '용호', '명서', '소답', '대원',
'반송', '중앙', '용지동', '상남', '사파', '가음', '성주', '웅남', '중동',
'구산', '진동', '진북', '진전', '현동', '가포', '월영', '문화동', '반월중앙', '반월 중앙',
'완월', '자산', '오동', '교방', '합포', '산호',
'회원1', '회원 1', '회원2', '회원 2', '석전', '회성', '양덕1', '양덕 1', '양덕2', '양덕 2',
'합성1', '합성 1', '합성2', '합성 2', '구암1', '구암 1', '구암2', '구암 2', '봉암',
'충무', '여좌', '태백', '경화', '병암', '석동', '이동', '자은', '덕산', '풍호',
'웅천', '웅동1', '웅동 1', '웅동2', '웅동 2'
]
이후 반복문으로 in
을 메인으로 하는 카운팅 코드를 작성했다.
# 반복문을 돌면서 '행정동 네임 딕셔너리의 키'가 '키 리스트'에 존재하는지 확인한다
# count_kitty_list로부터 행정동 이름 하나를 가져온다
for keyword in count_kitty_list:
# ['행정구', '행정동']으로 구성된 data_set에서 하나씩 data에 가져온다
for data in data_set:
# 만약 행정동 이름이 ['행정구', '행정동']의 '행정동' 문자열 안에 포함된다면
if keyword in data[1]:
# 딕셔너리의 해당 keyword와 대응하는 값에 1을 더한다
count_kitty_dict[keyword]+=1
# ['행정구', '행정동']의 '행정동' 문자열에 포함되지 않는다면
elif keyword not in data[1]:
# 알수 없음 바구니에 '행정동' 문자열이 있는지 확인하고
if data[1] not in count_unknown:
# 없다면 집어넣는다
count_unknown.append(data[1])
# 행정동 이름이 포함되지 않은 위치 정보를 따로 저장하기 위해서 이렇게 했다
이렇게 해서도 잡히지 않는 문자열이 있다.
예를 들어 아래와 같은 구성인데도
if '팔용' in '팔용동파티마사거리':
value에 1을 더한다
이걸 잡아내지 못한다.
행정동 네임 리스트(count_kitty_list)와 행정동 네임 딕셔너리(count_kitty_dict)에 '팔용동'과 같은 문자열을 추가해가면서 진행했지만 만족스러운 결과가 나오지 않는다.
지금까지는 아래의 단계까지 작성했다.
# 반복문을 돌면서 '행정동 네임 딕셔너리의 키'가 '키 리스트'에 존재하는지 확인한다
# count_kitty_list로부터 행정동 이름 하나를 가져온다
for keyword in count_kitty_list:
# ['행정구', '행정동']으로 구성된 data_set에서 하나씩 data에 가져온다
for data in data_set:
# 만약 행정동 이름이 ['행정구', '행정동']의 '행정동' 문자열 안에 포함된다면
if keyword in data[1]:
# 딕셔너리의 해당 keyword와 대응하는 값에 1을 더한다
count_kitty_dict[keyword]+=1
# ['행정구', '행정동']의 '행정동' 문자열에 포함되지 않는다면
elif keyword not in data[1]:
# 알 수 없음 바구니에 '행정동' 문자열이 있는지 확인하고
if data[1] not in count_unknown:
# 없다면 집어넣는다
count_unknown.append(data[1])
# 행정동 이름이 포함되지 않은 위치 정보를 알 수 없음 바구니에 따로 저장하기 위해서 이렇게 했다
# 다시 한 번 count_kitty_list로부터 행정동 이름 하나씩을 집어든다
for keyword in count_kitty_list:
# 알 수 없음 바구니를 뒤져볼 것이다
for data in count_unknown:
# 만약 바구니에서 행정동 이름을 혹시라도 발견한다면
if keyword in data:
while True:
# 해당 행정동의 value에 1을 더해준다
count_kitty_dict[keyword] += 1
# 그러고 나서 알 수 없음 바구나에서 해당 값을 삭제한다
count_unknown.remove(data)
# 혹시 모르니 완벽하게 지운다
if data not in count_unknown:
break
# 행정동 딕셔너리에서 카운트를 조회하는 코드
for i in count_kitty_dict:
if count_kitty_dict[i] > 0:
print(i, count_kitty_dict[i])
대량의 데이터를 다루는 과정에서 뭔가 오류가 있나? 생각했지만 그런 게 아닐 것이다.
분명 어딘가 잘못된 곳이 있을 텐데 그 부분을 잡아 내는 것에 집중해야겠다.
오늘은 여기까지.