본문 바로가기
수업(국비지원)/Python

[Python] 빅데이터 분석 예제

by byeolsub 2023. 4. 25.
#################### 빅데이터이용
'''
행정안전부 : <https://www.mois.go.kr/>
  정책자료 -> 연령별 인구현황 -> csv파일 다운
'''

 

📌

import numpy as np
import csv
import re
f = open("data/age.csv")
data = csv.reader(f) # csv 형태의 파일을 읽어 저장
type(data) # _csv.reader
data # 반복문을 통해 한행씩 조회가능

import matplotlib.pyplot as plt
name = "역삼"
for row in data : # row : 한개의 행
    if row[0].find(name) >= 0 : # 행정구역의 내용에 name값이 존재?
        print(row)
        name=row[0]
        # 숫자의 , 제거
        row = list(map((lambda x : x.replace(",","")), row))
        print(row)
        # 0세 컬럼 이후의 셀들을 배열로 생성
        home = np.array(row[3:],dtype=int)
        print(home)
        break # 반복문 종료
        
# home : 해당 동(읍)의 나이별 인구수를 배열로 저장
plt.style.use('ggplot') # 그래프 스타일 설정
plt.figure(figsize=(10,5),dpi=100) # 그래프 크기 지정 
plt.rc('font',family='Malgun Gothic') # 한글 설정
plt.title(name + ' 지역의 인구 구조') # 그래프 제목 설정
plt.plot(home) # 선 그래프 출력

name 부분에 이름이 바뀌면 그래프도 달라진다.


'''
기본 함수
   np.arange(15) : 0 ~ 14까지의 숫자를 1차원 배열로 생성
   arr.reshape(3,5) : 3행5열의 2차원배열로 생성.  배열 갯수가 맞아야 함.
   arr.dtype : 배열 요소의 자료형
   arr.shape :배열 구조 행열값
   arr.ndim  : 배열의 차수
   arr.itemsize : 요소의 바이트 크기
   arr.size : 요소의 갯수 
   np.zeros((행,열)) : 요소의 값이 0인 배열 생성
   np.ones((행,열)) : 요소의 값이 1인 배열 생성
                      np.ones(10,dtype=자료형)
   np.eye(10,10) #10행10열 단위 행렬
   np.linspace(시작값,종료값,갯수) : 시작값부터 종료값까지 갯수만큼 균등분할하는 수치
   np.pi : 원주율 상수

난수 관련 함수
   np.random.random() : 난수 발생
   np.random.default_rng(1) : seed 값 설정
   np.random.randint: 정수형 난수 리턴. 
   np.random.normal(평균,표준편차,데이터갯수) : 정규 분포 난수 생성
   np.random.choice(값의범위,선택갯수,재선택여부)
   np.random.choice(값의범위,선택갯수,확률)

통계 관련 함수
   sum,min,max,mean,std
   max(axis=1) : 행중 최대값
   max(axis=0) : 열중 최대값
   cumsum(axis=1) : 행의 누적 합계
   cumsum(axis=0) : 열의 누적 합계
   argmax(axis=1) : 행 중 최대값의 인덱스
   argmin(axis=1) : 행 중 최소값의 인덱스
   argmax(axis=0) : 열 중 최대값의 인덱스
   argmin(axis=0) : 열 중 최소값의 인덱스
   
  np.fromfunction() : 함수를 이용하여 요소의 값 설정
  arr.flat:배열의 요소들만 리턴
  np.floor: 작은 근사정수
  np.ceil : 큰 근사정수
  
  arr.ravel() #1차원배열로 변경
  arr.resize() : 배열 객체 자체를 변경

2개의 배열을 합하기
   np.vstack((i,j)) #행기준 합. 열의 갯수가 같아야 함
   np.hstack((i,j)) #열기준 합. 행의 갯수가 같아야 함.

배열 나누기
   np.hsplit(k,3) #3개로 열을 분리. 
   np.vsplit(k,2) #2개로 행을 분리. 
'''

📌

# test1207 내용 중
'''
0. 인구구조의 그래프 제목에 코드값 제거하기 
'''
import csv
f = open("data/age.csv")
data = csv.reader(f) # csv 형태의 파일을 읽어 저장
type(data) # csv형태 파일. _csv.reader
data # 반복문을 통해 한행씩 조회가능. 

import re #  정규식 이용을 위한 모듈
import numpy as np
import matplotlib.pyplot as plt
name = "신사"
# data를 반복문으로 읽으면, 다시 처음부터 시작 할 수 없음. 
# 처음부터 다시 시작하고 싶으면 다시 읽어야 한다. 
for row in data : # row : 한개의 행
    if row[0].find(name) >= 0 : # 행정구역의 내용에 name값이 존재?
        print(row)
        name=row[0]
        # row[0]의 코드값 제거
        # re.sub(패턴 문자, 변경문자, 대상이 되는 문자열) : 치환 함수
        # \\( : 그룹을 의미하는 것이 아니고 ( 문자를 의미.
        # \\\\d : 숫자0개 이상을 의미
        # \\) : )문자를 의미.
        name = re.sub("\\(\\d*\\)","",row[0])
        # 숫자의 , 제거
        row = list(map((lambda x : x.replace(",","")), row))
        print(row)
        # 0세 컬럼 이후의 셀들을 배열로 생성
        home = np.array(row[3:],dtype=int)
        print(home)
        break # 반복문 종료
        
# home : 해당 동(읍)의 나이별 인구수를 배열로 저장
plt.style.use('ggplot') # 그래프 스타일 설정
plt.figure(figsize=(10,5),dpi=100) # 그래프 크기 지정 
plt.rc('font',family='Malgun Gothic') # 한글 설정
plt.title(name + ' 지역의 인구 구조') # 그래프 제목 설정
plt.plot(home) # 선 그래프 출력

### 같은 이름을 포함한 동이 있는 경우 모든 동을 하나의 그래프로 작성하기
f = open("data/age.csv")  # f : IOStream 
data = csv.reader(f) # data : age.csv 파일의 정보를 저장하고 있는 객체.
                     #        스트림을 통해 들어왔기 때문에 되돌릴 수는 없다. 
next(data) # 한줄을 읽기. 
data = list(data) # 파일스트림데이터를 리스트객체로 변경
                  # 파일내용을 리스트로 저장
data # 리스트 객체                  
name = "신사" 
homelist = [] # 신사라는 이름을 가진 행정동의 인구데이터를 저장해주는 리스트 객체
namelist = [] # 동이름목록을 저장

for row in data :
    # row : 각 동별 인구데이터 한개.
    if row[0].find(name) >= 0 :
        # 숫자의 , 를 제거
        row = list(map((lambda x:x.replace(",","")),row))
        # row[3:] : 0세이후 인구목록
        homelist.append(np.array(row[3:],dtype = int))
        # 동의 이름을 (이전 부분까지만 이름 목록에 추가
        # row[0].find('(') : row[0]문자열에서 '('문자의 인덱스
        namelist.append(row[0][:row[0].find('(')])
        
plt.style.use('ggplot') 
plt.figure(figsize=(10,5),dpi=100) 
plt.rc('font', family='Malgun Gothic')
plt.title(name + '지역의 인구 구조')
for h,n in zip(homelist,namelist) :
    # h : 그래프로 출력할 데이터 
    # n : 동의 이름
    plt.plot(h,label=n) # 하나의 그래프에 여러개의 선그래프 작성         
plt.legend() # 범례 출력

 


📌

### age.csv 파일을 이용하여 선택한 지역의 인구구조와 
#   가장 비슷한 인구구조를 가진 지역의 그래프와 지역 출력하기.
#   가장 비슷한 지역 한개만 그래프로 출력하기.
name = "역삼1동"
for row in data : 
    if name in row[0] : #row[0] 문자열에 name포함?
        #,를 제거 : 숫자내부의, 제거
        row = list(map((lambda x:x.replace(",","")),row))
        #np.array
        #int(row[2]) : 정수형 총인구수
        #home : 0세이후 인구수를 정수형배열 / 총인구수
        #       총인구수 대비 각각의 나이의 비율 목록
        #       name에 해당하는 동의 나이별 인구 비율 목록
        home = np.array(row[3:],dtype=int) / int(row[2])
        home_name = re.sub('\\(\\\\d*\\)','',row[0])
mn = 1
for row in data :
    #숫자의 ,제거
    row = list(map((lambda x:x.replace(",","")),row))
    #현재 레코드의 인구 비율 정보
    away = np.array(row[3:],dtype=int) / int(row[2])
    # name의 동과 다른지역의 데이터의 차의 제곱의 합.
    # s값이 가장 작은 지역이 name 동과 가장 비슷한 인구구조 지역
    s = np.sum((home - away) ** 2)
    #s < mn : 다른지역의 오차합이 더작은지역 mn과 가장 가까운 지역
    #name not in row[0] : name의 지역이 아닌 조건
    if s < mn and name not in row[0] :
        mn = s
        #result_name : 현재까지 가장 오차가 적은 지역의 이름
        result_name = re.sub('\\(\\\\d*\\)','',row[0])
        #result : 현재까지 가장 오차가 적은 지역 데이터
        result = away

#home : name 동의 데이터,
#home_name : name 동의 행정구역 이름
#result : data 중 가장 오차합이 작은 지역의 데이터
#result_name : 오차합이 작은 지역의 이름

plt.style.use('ggplot') 
plt.figure(figsize=(10,5),dpi=100) 
plt.rc('font', family='Malgun Gothic')
plt.title(name + '지역과 가장 비슷한 인구 구조를 가진 지역') 
plt.plot(home, label = home_name) 
plt.plot(result,label = result_name)
plt.legend()
plt.show()


 📌

### pandas를 이용한 분석
import pandas as pd
df = pd.read_csv("data/age.csv") 

# 오류발생.
# 'utf-8' codec can't decode byte 0xc7 in position 1: invalid continuation byte
'''
		age.csv  파일 cp949 형태의 파일임. ANSI형태의 파일. EUC-KR, KSC5601..
    cp949 형태 : 우리나라에서의 기본파일 해외에서는 UTF-8
    csv모듈, open함수를 이용한 경우 기본인코딩이 cp949임.
    MAC은 기본 인코등 방식이 UTF-8임.
    이때까지 윈도우환경의 경우 기본인코딩이 cp949여서 에러가 나지 않은것.
    맥의 경우 인코딩 설정 따로 해주어야 에러가 나지 않는다.   
'''

import pandas as pd
# thousands="," : 숫자의 세자리 마다,를 제거하고 순수한 숫자로만 인식
# index_col=0 : 0번 컬럼을 인덱스로 설정
#               행정구역 컬럼이 인덱스로 설정됨
df = pd.read_csv("data/age.csv",encoding="cp949",thousands=",",index_col=0) 
df.head()
df.info()
df.columns

# 컬럼명을 변경
col_name = ['총인구수','연령구간인구수']
for i in range(0,101) : # 0~100
    col_name.append(str(i) + '세')
col_name
df.columns = col_name
df.columns    

# df의 모든 컬럼들을 총인구수로 나누기. 비율로 저장
# (인구구조를 찾는것)
df = df.div(df["총인구수"],axis=0)
df.head()

# 총인구수, 연령구간인구수 컬럼 제거하기
del df["총인구수"],df["연령구간인구수"]
df.info()
df.count() # 해당 컬럼의 결측값이 아닌 데이터의 건수. 
 
# 결측값을 0으로 치환
# fillna : 결측값을 다른값으로 치환
df.fillna(0,inplace=True) # 결측값을 0으로 치환
↑
코드 전치처리

# 지정한 지역과 가장 비슷한 인구구조를 갖는 지역 찾아 그래프로 출력
name = "역삼2동"

# df.index : 행정구역명
# df.index.str : 인덱스의 이름을 문자열로 변경
# df.index.str.contains() : 선택된 이름을 포함?
#                           지정한 이름을 가진 레코드만 True
a = df.index.str.contains(name)
a
df2 = df[a]
df2 # 지정한 지역의 데이터

# row[0]에서 코드 삭제하기
names = list(df2.index)
names[0] = names[0][:names[0].find('(')]
df2.index = names

# a값을 제외한 다른데이터만 저장
b = list(map(lambda x : not x,a))
b
df3 = df[b]

mn = 1
for label, content in df3.T.items() : 
    # label : 컬럼명. 각각의 행정동명
    # content : 행정동 데이터 
    # s : 지정된 지역과 현재데이터의 오차 합
    s = sum((content - df2.iloc[0]) ** 2)
    if s < mn :
        mn = s
        result = content
        name = result.name
        result.name = name[:name.find('(')] # row[0]에서 코드 삭제하기
        
df2.T.plot() # 지정된 데이터
result.plot(legend = result_name)
plt.legend()

 

 

'수업(국비지원) > Python' 카테고리의 다른 글

[Python] 중복된 데이터 처리  (0) 2023.04.25
[Python] 데이터 전처리  (0) 2023.04.25
[Python] numpy 연산  (0) 2023.04.25
[Python] numpy 행렬  (0) 2023.04.25
[Python] 지도를 이용한 시각화2  (0) 2023.04.25