python: *csv 데이터 처리 실습

0

압축 Python

목록 보기
10/11
post-thumbnail

창원시 불법 주정차 단속 위반에 관한 파일을 전처리 하려고 한다.

파일 내용 불러오기

## 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)

리스트를 또다시 새로 만들었다.

  • 0번 인덱스: 행정구
  • 1번 인덱스: 행정동

행정구와 행정동의 카운트를 나누어서 해볼 생각이다.

행정구의 경우 'ㅇㅇ구'로 이름이 명확하다.
행정동은 이름이 중구난방이라 미리 딕셔너리를 만들어야겠다.

먼저 간단해보이는 행정구부터 카운트 해보겠다.

# 행정구 카운트하기
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])

대량의 데이터를 다루는 과정에서 뭔가 오류가 있나? 생각했지만 그런 게 아닐 것이다.
분명 어딘가 잘못된 곳이 있을 텐데 그 부분을 잡아 내는 것에 집중해야겠다.

오늘은 여기까지.


0개의 댓글