[Python] 2019-2H 질병 데이터 분석하기 Analyzing disease data
본문 바로가기

Data_Science

[Python] 2019-2H 질병 데이터 분석하기 Analyzing disease data

2019-2H Introduction to Software Convergence

 

 

총 네가지 주제로 구성되어있다.

 

  • 1-1. 성별 별, 가장 자주 이용하는 병원은 어디일까?
  • 1-2. 연령대 별, 가장 자주 이용하는 병원은 어디일까?
  •  
  • 2-1. 성별 별, 가장 많이 걸리는 질병은 무엇일까?
  • 2-2. 연령대 별, 가장 많이 걸리는 질병은 무엇일까?
  •  

데이터는 

  1. 공공데이터포털을 통해서


         1) 2016년도 진료 내역 정보를 수집. 
             

 

-진료내역정보는 국민건강보험가입자 중 해당 년도에 요양(병/의원)기관으로 부터의 진료내역이 1건 이상 있는 가입자 100만 명을 무작위로 선별하고, 항목 선정 과정을 거쳐 선정된 해당 가입자의 기본정보와 진료정보를 추출하여 구성한 정보이다. 
          
         2) 국민건강정보데이터 진료내역정보 사용자 매뉴얼의 진료 과목별 코드를 csv파일로 저장.

2. 통계분류표털 KCD 한국표준질병·사인분류를 수집 (제 7차 개정)

 

하여 사용하였다.

 


1-1 성별 별, 가장 자주 이용하는 병원은 어디일까?

 

Code:

더보기

 

import csv
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
from matplotlib import style

font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)
style.use('ggplot')
plt.rcParams['xtick.labelsize'] = 100
plt.rcParams['ytick.labelsize'] = 100

man=[]
woman=[]
subject=[]

for i in range(0,89):
    man.append(0)
    woman.append(0)

### 여성, 남성 별 진료과목 나누기

f_main = open('2016.csv', 'r', encoding='cp949')

rdr1 = csv.reader(f_main)

for line in rdr1:
    num_man=0
    num_woman=0
    if line[3]=='1':
        if line[8].isdigit()==True:
            num_man=int(line[8])
            man[num_man]+=1
        else:
            pass
    if line[3]=='2':
        if line[8].isdigit()==True:
            num_woman=int(line[8])
            woman[num_woman]+=1
        else:
            pass
f_main.close()   

### 진료 과목 라벨 작성

f_subject = open('subject_code.csv', 'r', encoding='utf-8')

rdr2 = csv.reader(f_subject)

for line in rdr2:
    subject.append(line[0])
f_subject.close()

### 진료 과목 코드와 숫자 맞추기

for j in range(60,80):
    del(woman[60])
    del(man[60])
for i in range(27,50):
    del(woman[27])
    del(man[27])
    
### 막대 그래프로 나타내기

##여성
plt.figure(figsize=(100,100))
plt.barh(subject, woman)
plt.show()

##남성
plt.figure(figsize=(100,100))
plt.barh(subject, man)
plt.show()

 

 

 

막대 그래프 실행 결과:

 

                남성 :

남성 이용 병원 막대그래프

                      여성 :

여성 이용 병원 막대그래프

 

 

워드 클라우드 Code:

더보기
### 워드 클라우드로 나타내기

## 여성
import matplotlib.pyplot as plt
from wordcloud import WordCloud
import numpy as np
from PIL import Image
from matplotlib import font_manager, rc
import os

text={}

for i in range(0,46):
    text[subject[i]] = int(woman[i])
    
text['여성'] = int(1000000)
heart_beat=np.array(Image.open("C:/Users/user/Desktop/2019-02/소프트웨어융합개론/질병 분석_termproject/hospital.jpg"))

wordcloud = WordCloud(font_path="C:/Users/user/AppData/Local/Microsoft/Windows/Fonts/DXLifeTheatreB-KSCpc-EUC-H.ttf", relative_scaling=0.1, mask=heart_beat, background_color='white').generate_from_frequencies(text)

plt.figure(figsize=(16,8))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()

# 남성

import matplotlib.pyplot as plt
from wordcloud import WordCloud
import numpy as np
from PIL import Image
from matplotlib import font_manager, rc
import os

text={}

for i in range(0,46):
    text[subject[i]] = int(man[i])
    
text['남성'] = int(1000000)
heart_beat=np.array(Image.open("C:/Users/user/Desktop/2019-02/소프트웨어융합개론/질병 분석_termproject/hospital.jpg"))


wordcloud = WordCloud(font_path="C:/Users/user/AppData/Local/Microsoft/Windows/Fonts/DXLifeTheatreB-KSCpc-EUC-H.ttf", relative_scaling=0.1, mask=heart_beat, background_color='white').generate_from_frequencies(text)

plt.figure(figsize=(16,8))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()

 

 

워드 클라우드 실행 결과:

 

                남성 :

남성 이용 병원 워드클라우드

                여성 :

여성 이용 병원 워드클라우드

 

결론

 

  1. 두 성별 모두 내과 > 정형외과 > 이비인후과... 순으로 높게 나타났음
  2. 남성/여성에서 두드러진 차이점은 남성은 비뇨기과의 비율이 높고, 여성은 산부인과의 비율이 높다는 점이었음

 

 


 

 

 

1-2 연령 별, 가장 자주 이용하는 병원은 어디일까?

 

Code:

더보기
import csv
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
from matplotlib import style
import heapq

subject=[]
age = []

for i in range(19):
    line = []
    for j in range(89):
        line.append(0)
    age.append(line)


### 연령 별 진료과목 나누기

f_main = open('2016.csv', 'r', encoding='cp949')

rdr1 = csv.reader(f_main)

for line in rdr1:
    num=0
    for i in range(19):
        if line[4] == str(i):
            if line[8].isdigit()==True:
                num=int(line[8])
                age[i][num]+=1
            else:
                pass 
       
            
   
### 진료 과목 라벨 작성

f_subject = open('subject_code.csv', 'r', encoding='utf-8')

rdr2 = csv.reader(f_subject)

for line in rdr2:
    subject.append(line[0])
f_subject.close()

### 진료 과목 코드와 숫자 맞추기
for i in range(19):
    for j in range(60,80):
        del(age[i][60])
for i in range(19):
    for j in range(27,50):
        del(age[i][27])  
        
data=pd.DataFrame(age)
data.to_csv('age.csv', encoding='cp949')
f_main.close()   

### 최상위 3개 계층 뽑아내기 + 라벨 붙이기

code_num=[]
code=[]
for i in range(19):
    line = []
    line2= []
    code_num.append(line)
    for j in range(3):
        line2.append(0)
    code.append(line2)


for i in range(1,19):
    code_num[i]=heapq.nlargest(3, range(len(age[i])), key=age[i].__getitem__)
    

for i in range(1,19):
    for j in range(0,3):
        a = 0
        a = code_num[i][j]
        code[i][j]=subject[a]
        
### 데이터 프레임으로 작성하기
data=pd.DataFrame(code)

data.columns = ['first', 'second', 'third']
data.index=['0','0-4세','5-9세','10-14세','15-19세','20-24세','25-29세','30-34세','35-39세','40-44세','45-49세','50-54세','55-59세','60-64세','65-69세','70-74세','75-79세','80-84세','85+  세']

data = data.drop(['0'])

data        
        

 

실행 결과 :

연령 별, 가장 자주 이용하는 병원

 

결론

 

  1. 0-14세는 내과, 이비인후과, 소아청소년과를 가장 많이 이용했다.
    • 나이가 증가하면서 '소아청소년'과의 비율이 점점 줄어드는 것을 직접 확인할 수 있었다.
  2. 15-39세는 내과, 이비인후과, 정형외과 순으로 많이 이용했다.
    • 30-34세 그룹에서 '산부인과'가 순위권에 등장했다.
    • 출산율이 높은 연령대이기 때문일 것으로 예상된다.
  3. 40-59세는 내과, 정형외가, 이비인후과 순으로 많이 이용했다.
  4. 60세 이후는 내과, 정형외과, 안과 순으로 많이 이용했다.

 

 


 

 

2-1 성별 별, 가장 많이 걸리는 질병은 무엇일까?

 

Code: 

더보기
import csv
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
from matplotlib import style
import heapq

code_m=[]
code_num_m=[]
code_w=[]
code_num_w=[]


### 여성, 남성 별 질병 나누기

f_main = open('2016.csv', 'r', encoding='cp949')

rdr1 = csv.reader(f_main)

for line in rdr1:
    if line[3]=='1':
        if len(line[9]) >= 3:
            if line[9][:3] in code_m:
                code_num_m[code_m.index(line[9][:3])]+=1
            else:
                code_m.append(line[9][:3])
                code_num_m.append(1)
        else:
            pass
                
    if line[3]=='2':
        if len(line[9]) >= 3:
            if line[9][:3] in code_w:
                code_num_w[code_w.index(line[9][:3])]+=1
            else:
                code_w.append(line[9][:3])
                code_num_w.append(1)
        else:
            pass
f_main.close() 

### 최상위 15개만 추출하기

code_final_m=[]
code_final_w=[]

for i in range(0, 15):
    code_final_m.append(code_m[heapq.nlargest(15, range(len(code_num_m)), key=code_num_m.__getitem__)[i]])
    code_final_w.append(code_w[heapq.nlargest(15, range(len(code_num_w)), key=code_num_w.__getitem__)[i]])


### 한국표준질병·사인분류와 매치시키기

subject_w=[]
subject_m=[]

f_main2 = open('Korean standard classification of disease and cause of death.csv', 'r', encoding='utf-8')

rdr2 = csv.reader(f_main2)

for i in range(0,15):
    for line in rdr2:
        if code_final_w[i] == line[3]:
            if line[2] == '':
                pass
            else:
                subject_w.append(line[6])
        if code_final_m[i] == line[3]:
            if line[2] == '':
                pass
            else:
                subject_m.append(line[6])
    f_main2.seek(0)    
f_main2.close() 

### 데이터 프레임으로 작성하기

data = pd.DataFrame(
    {
     '남성': subject_m,
     '여성': subject_w
    })
data.index=['1위','2위','3위','4위','5위','6위','7위','8위','9위','10위','11위','12위','13위','14위','15위']

data

 

실행 결과 :

성별 별 질병 순위

 

 

워드 클라우드 Code :

더보기
### 워드 클라우드로 작성하기 위해 모든 경우의 수 매치시키기

subject_w=[]
subject_m=[]

f_main2 = open('Korean standard classification of disease and cause of death.csv', 'r', encoding='utf-8')

rdr2 = csv.reader(f_main2)

for i in range(len(code_m)):
    for line in rdr2:
        if code_m[i] == line[3]:
            if line[2] == '':
                pass
            else:
                subject_m.append(line[6])
    f_main2.seek(0) 

for i in range(len(code_w)):
    for line in rdr2:    
        if code_w[i] == line[3]:
            if line[2] == '':
                pass
            else: 
                subject_w.append(line[6])
    f_main2.seek(0)  
    
f_main2.close() 

### 워드클라우드로 나타내기

##남성

import matplotlib.pyplot as plt
from wordcloud import WordCloud
import numpy as np
from PIL import Image
from matplotlib import font_manager, rc
import os

text={}

for i in range(len(subject_m)):
    text[subject_m[i]] = int(code_num_m[i])
    
text['남성'] = int(1000000000)
heart_beat=np.array(Image.open("C:/Users/user/Desktop/2019-02/소프트웨어융합개론/질병 분석_termproject/hospital.jpg"))

#from wordcloud import ImageColorGenerator
#image_colors = ImageColorGenerator(heart_beat)

wordcloud = WordCloud(font_path="C:/Users/user/AppData/Local/Microsoft/Windows/Fonts/DXLifeTheatreB-KSCpc-EUC-H.ttf", relative_scaling=0.1, mask=heart_beat, background_color='white').generate_from_frequencies(text)

plt.figure(figsize=(16,8))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()

##여성

text={}

for i in range(len(subject_w)):
    text[subject_w[i]] = int(code_num_w[i])
    
text['여성'] = int(1000000000)
heart_beat=np.array(Image.open("C:/Users/user/Desktop/2019-02/소프트웨어융합개론/질병 분석_termproject/hospital.jpg"))

#from wordcloud import ImageColorGenerator
#image_colors = ImageColorGenerator(heart_beat)

wordcloud = WordCloud(font_path="C:/Users/user/AppData/Local/Microsoft/Windows/Fonts/DXLifeTheatreB-KSCpc-EUC-H.ttf", relative_scaling=0.1, mask=heart_beat, background_color='white').generate_from_frequencies(text)

plt.figure(figsize=(16,8))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()

 

워드 클라우드 실행 결과:

 

                남성 :

남성 질병 순위 워드 클라우드

 

 

                여성 :

여성 질병 순위 워드 클라우드

결론

 

  1. 두 성별 모두 급성 기관지염, 고혈압이 가장 많았다.
  2. 남성에서는 여성에서 볼 수 없었던 '전립성 증식증'이 순위에 등장하였다.
  3. 남성보다 훨씬 더 많은 수의 여성이 '무릎 관절증'을 호소하였다.

 


 

 

2-2 연령 별, 가장 많이 걸리는 질병은 무엇일까?

 

 

Code :

더보기
import csv
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
from matplotlib import style
import heapq

code=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
code_num=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]

### 연령 별 질병 나누기
    
f_main = open('2016.csv', 'r', encoding='cp949')

rdr1 = csv.reader(f_main)

for line in rdr1:
    for i in range(1,19):
        if line[4] == str(i):
            if len(line[9]) >= 3:
                if line[9][:3] in code[i]:
                    code_num[i][code[i].index(line[9][:3])]+=1
                else:
                    code[i].append(line[9][:3])
                    code_num[i].append(1)
            else:
                pass               


f_main.close() 

### 최상위 5개만 추출하기

code_final=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]

for i in range(1, 19):
    for j in range(0, 5):
        code_final[i].append(code[i][heapq.nlargest(5, range(len(code_num[i])), key=code_num[i].__getitem__)[j]])
        
### 한국표준질병·사인분류와 매치시키기
        
f_main2 = open('Korean standard classification of disease and cause of death.csv', 'r', encoding='utf-8')

subject=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]

rdr2 = csv.reader(f_main2)

for j in range(1, 19):
    for i in range(0,5):
        for line in rdr2:
            if code_final[j][i] == line[3]:
                if line[2] == '':
                    pass
                else:
                    subject[j].append(line[6])
        f_main2.seek(0)    
f_main2.close() 


### 데이터 프레임으로 작성하기

data=pd.DataFrame(subject)

data.columns = ['first', 'second', 'third', 'fourth', 'fifth']
data.index=['0','0-4세','5-9세','10-14세','15-19세','20-24세','25-29세','30-34세','35-39세','40-44세','45-49세','50-54세','55-59세','60-64세','65-69세','70-74세','75-79세','80-84세','85+  세']

data = data.drop(['0'])

data

 

 

 

실행 결과 :

연령 별 질병 순위

 

결론 : 

  1. 크게 0-49세는 급성 기관지염에 50세 이후는 고혈압에 가장 많이 걸리는 것으로 나타났다.
  2. 이후 0-39세는 비염, 편도염 순으로 많이 걸렸다.
  3. 40세 이후부터는 고혈압이 순위에 등장하기 시작했다.
  4. 50세 이후부터는 당뇨병, 무릎관절증, 등통증이 나타나기 시작했다.

느낀 점 : 

1) 현재 2016년 자료로 텀프로젝트를 진행했는데, 보고서에 작성하지는 않았지만 2017년 자료도 크롤링해본 결과, 2016년과 같은 양상으로 결과가 나타났다. 

2) 연령대별 자주 이용하는 병원과 자주 걸리는 질병으로 청소년층/청년층/중장년층/노년층이 나뉘어진다는 것을 직접 확인할 수 있어서 매우 신기했다. 

3) 워드 클라우드를 통해 분석한 자료들을 직접 시각화할 수 있어서 좋은 경험이었다.