본문 바로가기

빅데이터

빅데이터분석-전국 작은 도서관과 지역별 독서량이 유의미한 관계에 있을까?

2024-1학기 빅데이터분석개론 기말고사

201635917 김다인

전국 작은 도서관 현황-지역별 독서량에 유의미한 영향을 끼치는가?

1. 서론

빅데이터분석이라는 말이 거창해 보일 수 있다. 나도 빅데이터분석개론 수업을 듣기 전까지는 그랬다. 코딩을 잘 다루고, 분석 모델을 많이 외우고, 수학적 지식이 있어야 한다고 생각했다. 이제는 너무나 당연하게 우리 일상에 빅데이터 분석이 들어가 있다. 우리가 경험적으로, 직관적으로 생각하고 판단하는 것들이 이제는 논리적이고 빅데이터를 활용하여 근거가 있는 결과물들이 흔하게 있다. 스포츠, 사업, 학교, 직장, 금융, 의료 등 모든 분야에서 사용되고 있다. 모든 분야에서 다루어지고 있는 만큼 일반인이 더 접근하기 쉬워지고 있는 상황이다. 배운 지식으로 과연 내 상황과 환경에 맞추어서 어떻게 활용할 수 있겠는가 생각해 보았다.

현재 경기도 구리시에서 어머니가 사립 작은 도서관을 20년 넘게 운영 중이다. 내가 어렸을 적에는 책이 흔했으며, 시립도서관에는 사람이 북적였고, 사립 작은 도서관의 활성화가 되던 시기였다. 현재는 체감상 느끼기에 독서량은 절대적으로 줄어들었으며 도서업계 자체가 작아지고 일부 웹소설계로 쏠리고 있다. 그러나 여전히 전국에는 많은 도서관과 작은 도서관이 존재하고 있다. 이제는 도서관들이 단순 도서 대여의 역할만 하는 공간이 아니다. 하나의 복합문화시설로 작용하고 있으며 많은 돌봄 교실의 현장이 되고 있고 어른들의 모임장소로도 이용되고 있다. 전국에 있는 많은 도서관과 작은 도서관들의 역할이 독서량과의 정비례 역할을 하고 있는지 조사해보고자 한다.

2. 본론

1) 오픈 데이터 설명

활용한 오픈 데이터는 공공데이터포탈에 있는 '문화체육관광부_국가도서관통계_전국작은도서관통계'이다. 2022년 기준으로 전국도서관 통계가 이루어져 있으며, 데이터의 개수는 6900건이다. 국민들에게 전국 작은 도서관 정보에 대한 통계정보를 구체적으로 제공하여 통계 데이터 활성화와 도서관 이용 장려를 유도하는 데이터이다. 데이터의 컬럼은 평가 연도, 도서관 구분, 도서관명, 행정구역, 시군구, 장서수, 사서수, 방문자수, 도서예산 순으로 이루어져 있다.

2) 데이터 보기

In [4]:
import os
import pandas as pd
file_path = r'C:\KDI\문화체육관광부_국가도서관통계_전국작은도서관통계_20221231 (1).csv'

#데이터 불러오기
if os.path.isfile(file_path):
    df1 = pd.read_csv(file_path, encoding='CP949')
else:
    print("File not found. Please check the path.")

#사용할 샘플 데이터 만들기

df1.to_csv('C:\KDI\library_sample.csv')

file_path = r'C:\KDI\library_sample.csv'

if os.path.isfile(file_path):
    lib_info = pd.read_csv(file_path, encoding='UTF-8')
else:
    print("File not found. Please check the path.")

lib_info.head(30)
Out[4]:
Unnamed: 0평가년도도서관구분도서관명행정구역시군구장서수사서수방문자수도서예산01234567891011121314151617181920212223242526272829
0 2022 LIBTYPE000002003 경희궁자이3단지 작은도서관 서울 종로구 2671 0 3650 0
1 2022 LIBTYPE000002003 꿈꾸는 평창동 작은도서관 서울 종로구 5390 0 4446 5478000
2 2022 LIBTYPE000002003 나무와 열매 어린이 도서관 서울 종로구 6825 0 3130 1500000
3 2022 LIBTYPE000002003 도담도담한옥도서관 서울 종로구 6390 0 9390 6301200
4 2022 LIBTYPE000002003 두산아파트문고 서울 종로구 3200 0 371 0
5 2022 LIBTYPE000002003 무악다솜방 서울 종로구 5625 0 4437 5336200
6 2022 LIBTYPE000002003 삼청공원 숲속도서관 서울 종로구 9501 1 28170 4080000
7 2022 LIBTYPE000002003 석천문화관 서울 종로구 16908 1 252 5000000
8 2022 LIBTYPE000002003 숭인마루 작은도서관 서울 종로구 7353 0 6525 5007700
9 2022 LIBTYPE000002003 어린이도서관 꿈과쉼 서울 종로구 11729 0 1252 1849930
10 2022 LIBTYPE000002003 영실도서관 서울 종로구 2870 0 1305 0
11 2022 LIBTYPE000002003 우리소리도서관 서울 종로구 5902 1 12768 10979420
12 2022 LIBTYPE000002003 이화마을 작은도서관 서울 종로구 7879 0 15794 5608100
13 2022 LIBTYPE000002003 작은도서관 뜰 서울 종로구 1500 0 783 0
14 2022 LIBTYPE000002003 종로수어영상도서관 서울 종로구 2577 0 955 820000
15 2022 LIBTYPE000002003 지혜만들기 작은도서관 서울 종로구 6403 0 4698 5646700
16 2022 LIBTYPE000002003 창이 작은도서관 서울 종로구 5047 0 5220 4936300
17 2022 LIBTYPE000002003 청운효자동 북카페 서울 종로구 8367 1 4176 5396000
18 2022 LIBTYPE000002003 청파도서관 서울 종로구 12425 0 3443 3524782
19 2022 LIBTYPE000002003 통인 어린이 작은도서관 서울 종로구 16662 2 4212 8995180
20 2022 LIBTYPE000002003 혜윰뜰 작은도서관 서울 종로구 2800 0 2190 500000
21 2022 LIBTYPE000002003 혜화마을 북카페 서울 종로구 6921 0 5220 5647700
22 2022 LIBTYPE000002003 홍파랑 북카페 서울 종로구 7888 0 1305 4564800
23 2022 LIBTYPE000002003 광희동 작은도서관 서울 중구 4051 0 4720 4500000
24 2022 LIBTYPE000002003 다산동작은도서관 서울 중구 10658 0 7350 5250000
25 2022 LIBTYPE000002003 덕수궁 롯데캐슬아파트 작은도서관 서울 중구 2800 0 3650 0
26 2022 LIBTYPE000002003 동화동 새마을작은도서관 서울 중구 15589 0 6831 12000000
27 2022 LIBTYPE000002003 북소리 서울 중구 1200 0 3650 0
28 2022 LIBTYPE000002003 서울역센트럴자이아파트 작은도서관 서울 중구 1000 0 3650 0
29 2022 LIBTYPE000002003 신당5동작은도서관 서울 중구 5031 0 6574 5250000

추가 비교 분석 자료로, 문화체육관광부에서 진행한

ㅇ 조사 대상 : (성인) 전국 19세 이상 남녀, (학생) 초등학교(46학년), 중학교, 고등학교 재학생 ㅇ 조사 기간

  • 2019.10.011. 0시 기준
  • 조사 대상 기간 : 2018. 10. 1. 2019. 9. 30. (1년간)
  • 조사 실시 기간 : 2019. 12. 16. 2020. 1. 23.

ㅇ 조사 지역 : 전국 17개 시도(제주도 및 세종시 포함) ㅇ 표본 규모 : (성인) 총 6,000명, (학생) 3,126명 ㅇ 표본 오차 : (성인) 95% 신뢰 수준에서 1.7%p, (학생) 95% 신뢰 수준에서 1.8%p ㅇ 자료수집방법

  • 성인 : 조사원에 의한 1:1 개별면접조사(타계식 조사)
  • 학생 : 조사원(또는 교사) 통제에 의한 자기기입식

의 통계 자료로 활용할 것이다.조사(자계식 조사)

3) 데이터 클린징

현재 작은 도서관 데이터에서 지역별 독서량, 방문수에 유의미한 영향을 끼칠 수 있는 것은 장서수, 방문자수, 도서예산이다. 좋은 도서관의 자격요건에는 여러 가지 있겠지만, 도서관의 제 역할을 가장 많이 하고 있다고 느낄 수 있는 부분은 당연 '방문자수'이다. 도서관에 있는 책을 읽는 독자들이 많을수록 도서관은 제 기능을 하고 있는 것이다. 도서관의 방문자수를 늘릴 수 있는 것은 그 도서관에 얼마나 많은 책들이 비치되어 있는가(장서수), 앞으로 신간 책을 얼마나 더 재빠르게 구비할 수 있는가(도서예산)로 확인할 수 있다. 또한, 작은 도서관은 책을 좋아하는 개인이 운영하는 경우가 많기 때문에 정식 사서가 없는 경우가 많다. 그렇기 때문에 데이터에도 사서가 0명이라고 되어 있는 곳이 흔하게 있다. 사서 수의 데이터는 그렇게 유의미하지 않다고 판단한다.

먼저, 결측 데이터가 있는지 확인한다.

In [5]:
lib_info.isnull()
Out[5]:
Unnamed: 0평가년도도서관구분도서관명행정구역시군구장서수사서수방문자수도서예산01234...68946895689668976898
False False False False False False False False False False
False False False False False False False False False False
False False False False False False False False False False
False False False False False False False False False False
False False False False False False False False False False
... ... ... ... ... ... ... ... ... ...
False False False False False False False False False False
False False False False False False False False False False
False False False False False False False False False False
False False False False False False False False False False
False False False False False False False False False False

6899 rows × 10 columns

In [6]:
lib_info.isnull().sum()
Out[6]:
Unnamed: 0    0
평가년도          0
도서관구분         0
도서관명          0
행정구역          0
시군구           0
장서수           0
사서수           0
방문자수          0
도서예산          0
dtype: int64

결측 데이터는 없다. 다음으로는, 이상데이터를 제거해야 한다. 방문자 수가 가장 중요한 데이터이므로, 최댓값 아웃라이어가 있는 것은 오히려 가설에 증거가 될 수 있는 좋은 단서이다. 그러나, 최솟값 아웃라이어에 있는 값들은 도서관의 유무가 독서량을 늘린다는 가설에 도움이 되지 않는다. 따라서 최솟값 아웃라이어를 먼저 구하고 이상 데이터로 판단한 후 제거한다.

In [7]:
# 방문자 수가 있는 데이터만 선택
if '방문자수' in lib_info.columns:
    visitors = lib_info['방문자수']
else:
    print(f"Column '{'방문자수'}' not found in the dataframe.")
    visitors = None

# IQR 계산
Q1 = visitors.quantile(0.25)
Q3 = visitors.quantile(0.75)
IQR = Q3 - Q1


# 최솟값 아웃라이어 기준
lower_bound = Q1 - 1.5 * IQR

print(Q1)
print(Q3)
print(IQR)
print(lower_bound)
939.0
4800.0
3861.0
-4852.5

lower_bound가 음수가 나왔기 때문에 사용할 수가 없다. 따라서 임의로 수를 정해서 제외한다. 평균적으로 하루에 한 명이 오지 않는다면, 도서관이 제 역할을 다 하지 못한다고 생각한다. 따라서, 방문자수가 365명 아래인 행들은 제외한다.

In [8]:
# 방문자 수가 있는 데이터만 선택
if '방문자수' in lib_info.columns:
    visitors = lib_info['방문자수']
else:
    print(f"Column '{'방문자수'}' not found in the dataframe.")
    visitors = None

# 방문자 수가 365명 이상인 데이터만 선택
filtered_lib_info = lib_info[lib_info['방문자수'] >= 365]
In [9]:
filtered_lib_info
Out[9]:
Unnamed: 0평가년도도서관구분도서관명행정구역시군구장서수사서수방문자수도서예산01234...68946895689668976898
0 2022 LIBTYPE000002003 경희궁자이3단지 작은도서관 서울 종로구 2671 0 3650 0
1 2022 LIBTYPE000002003 꿈꾸는 평창동 작은도서관 서울 종로구 5390 0 4446 5478000
2 2022 LIBTYPE000002003 나무와 열매 어린이 도서관 서울 종로구 6825 0 3130 1500000
3 2022 LIBTYPE000002003 도담도담한옥도서관 서울 종로구 6390 0 9390 6301200
4 2022 LIBTYPE000002003 두산아파트문고 서울 종로구 3200 0 371 0
... ... ... ... ... ... ... ... ... ...
6894 2022 LIBTYPE000002003 호근새마을작은도서관 제주 서귀포시 4974 0 1095 1500000
6895 2022 LIBTYPE000002003 희망새마을작은도서관 제주 서귀포시 3002 0 2088 1000000
6896 2022 LIBTYPE000002003 (신례1리)예촌작은도서관 제주 서귀포시 7002 0 1305 2000000
6897 2022 LIBTYPE000002003 93대대독서대학 제주 서귀포시 1336 0 730 0
6898 2022 LIBTYPE000002003 LH강정작은도서관 제주 서귀포시 2281 0 1305 4000000

6106 rows × 10 columns

행이 약, 800행 정도 삭제되었다. 인덱스 번호는 그대로이므로, 다시 인덱스 번호를 순서대로 매겨준다.

In [10]:
filtered_lib_info.reset_index(drop=True, inplace=True)
filtered_lib_info
Out[10]:
Unnamed: 0평가년도도서관구분도서관명행정구역시군구장서수사서수방문자수도서예산01234...61016102610361046105
0 2022 LIBTYPE000002003 경희궁자이3단지 작은도서관 서울 종로구 2671 0 3650 0
1 2022 LIBTYPE000002003 꿈꾸는 평창동 작은도서관 서울 종로구 5390 0 4446 5478000
2 2022 LIBTYPE000002003 나무와 열매 어린이 도서관 서울 종로구 6825 0 3130 1500000
3 2022 LIBTYPE000002003 도담도담한옥도서관 서울 종로구 6390 0 9390 6301200
4 2022 LIBTYPE000002003 두산아파트문고 서울 종로구 3200 0 371 0
... ... ... ... ... ... ... ... ... ...
6894 2022 LIBTYPE000002003 호근새마을작은도서관 제주 서귀포시 4974 0 1095 1500000
6895 2022 LIBTYPE000002003 희망새마을작은도서관 제주 서귀포시 3002 0 2088 1000000
6896 2022 LIBTYPE000002003 (신례1리)예촌작은도서관 제주 서귀포시 7002 0 1305 2000000
6897 2022 LIBTYPE000002003 93대대독서대학 제주 서귀포시 1336 0 730 0
6898 2022 LIBTYPE000002003 LH강정작은도서관 제주 서귀포시 2281 0 1305 4000000

6106 rows × 10 columns

그다음으로는 중요하지 않은 컬럼을 삭제해야 한다. 먼저 사서 수 컬럼을 삭제해야 한다.

In [11]:
filtered_lib_info.pop('사서수')
Out[11]:
0       0
1       0
2       0
3       0
4       0
       ..
6101    0
6102    0
6103    0
6104    0
6105    0
Name: 사서수, Length: 6106, dtype: int64

이전에 미리 삭제해서 에러가 뜨지만, 사서수 컬럼이 잘 삭제된 것을 볼 수 있다.

In [12]:
filtered_lib_info
Out[12]:
Unnamed: 0평가년도도서관구분도서관명행정구역시군구장서수방문자수도서예산01234...61016102610361046105
0 2022 LIBTYPE000002003 경희궁자이3단지 작은도서관 서울 종로구 2671 3650 0
1 2022 LIBTYPE000002003 꿈꾸는 평창동 작은도서관 서울 종로구 5390 4446 5478000
2 2022 LIBTYPE000002003 나무와 열매 어린이 도서관 서울 종로구 6825 3130 1500000
3 2022 LIBTYPE000002003 도담도담한옥도서관 서울 종로구 6390 9390 6301200
4 2022 LIBTYPE000002003 두산아파트문고 서울 종로구 3200 371 0
... ... ... ... ... ... ... ... ...
6894 2022 LIBTYPE000002003 호근새마을작은도서관 제주 서귀포시 4974 1095 1500000
6895 2022 LIBTYPE000002003 희망새마을작은도서관 제주 서귀포시 3002 2088 1000000
6896 2022 LIBTYPE000002003 (신례1리)예촌작은도서관 제주 서귀포시 7002 1305 2000000
6897 2022 LIBTYPE000002003 93대대독서대학 제주 서귀포시 1336 730 0
6898 2022 LIBTYPE000002003 LH강정작은도서관 제주 서귀포시 2281 1305 4000000

6106 rows × 9 columns

4) 데이터 탐색

그룹화를 어떻게 할 것인가는 딱히 고민할 필요 없다. 작은 도서관의 유무에 따라 지역별 독서량 증가 유무를 알고 싶으니, 행정구역별-시군구별로 그룹화를 하여 방문자 수를 살피면 된다. 먼저, <2019년 국민 독서실태 조사>에서 조사한 내용이다.

<2019년 국민 독서실태 조사>의 지역별 주요 독서지표 분석한 결과, 성인의 경우 중소도시 및 읍면 지역 거주자들의 독서 지표가 대도시(서울 및 광역시) 거주자들보다 독서 지표가 낮은 것으로 보인다. 중소도시 및 읍면 지역에 거주하는 성인의 독서율(종이책+전자책+오디오북 종합독서율 기준)은 대도시 거주자보다 각각9.3%p, 27.6%p 낮다. 반면, 초중고 학생의 경우에는 지역 간 독서지표가 큰 차이가 없는 것으로 나타난다. 연간 독서량은 대도시 거주 학생들에 비해 중소도시 및 읍면 거주 학생들이 약 5권 정도 더 많으며, 공공도서관 이용률 역시 중소도시 및 읍면에 거주하는 학생들이 대도시에 거주하는 학생보다 7%p 정도 높은 것으로 나타난다. 

전국 17개 시도의 지역별 5대 독서 지표 분석 결과, 항목별 평균치 이상 항목이 5개인 곳은 서울, 인천, 제주였고, 경기와 강원이 4개 항목, 대구가 3개 항목, 부산, 울산, 세종이 2개 항목에서 전국 평균 이상의 실적을 나타내 상대적으로 독서 실태가 양호하다고 볼 수 있다. 반면 대전, 충북, 충남, 전북, 전남, 경북, 경남은 5대 독서 지표 모두가 평균치 이하로 보인다. 전국으로 비교했을 때, 상대적으로 독서 실태가 좋지 않은 지역으로 볼 수 있다.

작은 도서관 현황 데이터에서 행정구역별 묶어서 방문자수, 장서수, 도서예산을 확인한다. 먼저, 어느 행정구역과 시군구가 있는지 확인해 본다.

In [13]:
# '행정구역' 및 '시군구' 컬럼의 고유값 추출
admin_regions = filtered_lib_info['행정구역'].unique()
cities = filtered_lib_info['시군구'].unique()

print("행정구역의 고유값:")
print(admin_regions)

print("\n시군구의 고유값:")
print(cities)
행정구역의 고유값:
['서울' '부산' '대구' '인천' '광주' '대전' '울산' '세종특별자치시' '경기' '강원' '충북' '충남' '전북'
 '전남' '경북' '경남' '제주']

시군구의 고유값:
['종로구' '중구' '용산구' '성동구' '광진구' '동대문구' '중랑구' '성북구' '강북구' '도봉구' '노원구' '은평구'
 '서대문구' '마포구' '양천구' '강서구' '구로구' '금천구' '영등포구' '동작구' '관악구' '서초구' '강남구' '송파구'
 '강동구' '서구' '동구' '영도구' '부산진구' '동래구' '남구' '북구' '해운대구' '사하구' '금정구' '연제구'
 '수영구' '사상구' '기장군' '수성구' '달서구' '달성군' '미추홀구' '연수구' '남동구' '부평구' '계양구' '강화군'
 '광산구' '유성구' '대덕구' '울주군' '다정중앙로' '다정북로' '다정남로' '도움1로' '도움3로' '만남로' '마음안1로'
 '남세종로' '국세청로' '나성북로' '달빛1로' '보람로' '반곡로' '시청대로' '달빛로' '보듬3로' '부강면' '집현서2로'
 '새롬남로' '새롬중앙로' '조치원읍' '다솜로' '소정면' '연동면' '장군면' '연기면' '전의면' '나리1로' '누리로'
 '나리로' '노을3로' '도원1로' '마음안로' '대평로' '수원시' '성남시' '의정부시' '안양시' '부천시' '광명시'
 '평택시' '동두천시' '고양시' '과천시' '구리시' '남양주시' '오산시' '시흥시' '안산시' '군포시' '의왕시' '하남시'
 '용인시' '파주시' '이천시' '안성시' '김포시' '화성시' '광주시' '양주시' '포천시' '여주시' '연천군' '가평군'
 '양평군' '춘천시' '원주시' '강릉시' '동해시' '태백시' '속초시' '삼척시' '홍천군' '횡성군' '영월군' '평창군'
 '정선군' '철원군' '화천군' '양구군' '인제군' '고성군' '양양군' '청주시' '충주시' '제천시' '보은군' '옥천군'
 '영동군' '증평군' '진천군' '괴산군' '음성군' '천안시' '공주시' '보령시' '아산시' '서산시' '논산시' '계룡시'
 '당진시' '금산군' '부여군' '서천군' '청양군' '홍성군' '예산군' '태안군' '전주시' '군산시' '익산시' '정읍시'
 '남원시' '김제시' '완주군' '진안군' '무주군' '장수군' '임실군' '순창군' '고창군' '부안군' '목포시' '여수시'
 '순천시' '나주시' '광양시' '담양군' '곡성군' '구례군' '고흥군' '보성군' '화순군' '장흥군' '강진군' '해남군'
 '영암군' '무안군' '함평군' '영광군' '장성군' '완도군' '진도군' '신안군' '포항시' '경주시' '김천시' '안동시'
 '구미시' '영주시' '영천시' '상주시' '문경시' '경산시' '의성군' '청송군' '영양군' '영덕군' '청도군' '고령군'
 '성주군' '칠곡군' '예천군' '봉화군' '울진군' '울릉군' '창원시' '진주시' '통영시' '사천시' '김해시' '밀양시'
 '거제시' '양산시' '의령군' '함안군' '창녕군' '남해군' '하동군' '산청군' '함양군' '거창군' '합천군' '제주시'
 '서귀포시']
In [15]:
# 행정구역별로 데이터를 그룹화하고 합산 및 카운팅
grouped_by_region = lib_info.groupby('행정구역').agg({
    '장서수': 'sum',
    '방문자수': 'sum',
    '도서예산': 'sum',
    '도서관명': 'count'
}).reset_index()

# 도서관명 컬럼의 이름을 '도서관 수'로 변경
grouped_by_region.rename(columns={'도서관명': '도서관 수'}, inplace=True)

# 결과 출력
grouped_by_region
Out[15]:
행정구역장서수방문자수도서예산도서관 수012345678910111213141516
강원 1175465 747614 554448010 224
경기 11534961 7476915 4784425986 1676
경남 3432930 2193482 1189481310 489
경북 1787252 1029986 657905670 293
광주 1601091 856766 586752990 346
대구 1574325 794620 673183961 219
대전 1459281 665219 577268177 244
부산 2348753 1985125 971633520 430
서울 7007964 5379867 2722215366 943
세종특별자치시 394395 227268 87407550 59
울산 1172909 802806 500926171 188
인천 1822653 1186865 664467380 300
전남 1603575 921384 583900035 337
전북 2360542 1405530 1114863500 352
제주 714530 329891 332226496 150
충남 1941777 1054556 722603535 389
충북 1346886 914052 505361170 260
In [25]:
grouped_by_region
Out[25]:
administrativebook_countvisitedbudgetlib_count012345678910111213141516
강원 1175465 747614 554448010 224
경기 11534961 7476915 4784425986 1676
경남 3432930 2193482 1189481310 489
경북 1787252 1029986 657905670 293
광주 1601091 856766 586752990 346
대구 1574325 794620 673183961 219
대전 1459281 665219 577268177 244
부산 2348753 1985125 971633520 430
서울 7007964 5379867 2722215366 943
세종특별자치시 394395 227268 87407550 59
울산 1172909 802806 500926171 188
인천 1822653 1186865 664467380 300
전남 1603575 921384 583900035 337
전북 2360542 1405530 1114863500 352
제주 714530 329891 332226496 150
충남 1941777 1054556 722603535 389
충북 1346886 914052 505361170 260
In [ ]:
 
In [ ]:
 
In [26]:
# 한글에서 영문으로 행정구역명 매핑 딕셔너리
korean_to_english = {
    '서울': 'Seoul',
    '부산': 'Busan',
    '대구': 'Daegu',
    '인천': 'Incheon',
    '광주': 'Gwangju',
    '대전': 'Daejeon',
    '울산': 'Ulsan',
    '세종특별자치시': 'Sejong',
    '경기': 'Gyeonggi',
    '강원': 'Gangwon',
    '충북': 'Chungcheongbuk',
    '충남': 'Chungcheongnam',
    '전북': 'Jeollabuk',
    '전남': 'Jeollanam',
    '경북': 'Gyeongsangbuk',
    '경남': 'Gyeongsangnam',
    '제주': 'Jeju'
}


# '행정구역' 컬럼의 값을 영문으로 변환하는 함수
def translate_to_english(row):
    return korean_to_english.get(row['administrative'], row['administrative'])

# '행정구역' 컬럼의 값을 영문으로 변환
grouped_by_region['administrative'] = grouped_by_region.apply(translate_to_english, axis=1)

# 결과 출력
grouped_by_region
Out[26]:
administrativebook_countvisitedbudgetlib_count012345678910111213141516
Gangwon 1175465 747614 554448010 224
Gyeonggi 11534961 7476915 4784425986 1676
Gyeongsangnam 3432930 2193482 1189481310 489
Gyeongsangbuk 1787252 1029986 657905670 293
Gwangju 1601091 856766 586752990 346
Daegu 1574325 794620 673183961 219
Daejeon 1459281 665219 577268177 244
Busan 2348753 1985125 971633520 430
Seoul 7007964 5379867 2722215366 943
Sejong 394395 227268 87407550 59
Ulsan 1172909 802806 500926171 188
Incheon 1822653 1186865 664467380 300
Jeollanam 1603575 921384 583900035 337
Jeollabuk 2360542 1405530 1114863500 352
Jeju 714530 329891 332226496 150
Chungcheongnam 1941777 1054556 722603535 389
Chungcheongbuk 1346886 914052 505361170 260

5) 데이터 분석

행정구역별 장서수, 방문자수, 도서예산, 도서관수 데이터프레임이 완성이 되었다. 각 컬럼별 기준으로 했을 때, 어느 행정구역이 높은 순위를 차지하는지 확인해 볼 수 있다.

In [27]:
#장서수 기준 내림차순
df_sorted_book = grouped_by_region.sort_values(by=['book_count'], ascending=False)
df_sorted_book
Out[27]:
administrativebook_countvisitedbudgetlib_count182137151131245616010149
Gyeonggi 11534961 7476915 4784425986 1676
Seoul 7007964 5379867 2722215366 943
Gyeongsangnam 3432930 2193482 1189481310 489
Jeollabuk 2360542 1405530 1114863500 352
Busan 2348753 1985125 971633520 430
Chungcheongnam 1941777 1054556 722603535 389
Incheon 1822653 1186865 664467380 300
Gyeongsangbuk 1787252 1029986 657905670 293
Jeollanam 1603575 921384 583900035 337
Gwangju 1601091 856766 586752990 346
Daegu 1574325 794620 673183961 219
Daejeon 1459281 665219 577268177 244
Chungcheongbuk 1346886 914052 505361170 260
Gangwon 1175465 747614 554448010 224
Ulsan 1172909 802806 500926171 188
Jeju 714530 329891 332226496 150
Sejong 394395 227268 87407550 59
In [29]:
#방문자수 별 내림차순
df_sorted_visited = grouped_by_region.sort_values(by=[ 'visited'], ascending=False)
df_sorted_visited
Out[29]:
administrativebook_countvisitedbudgetlib_count182713111531216410506149
Gyeonggi 11534961 7476915 4784425986 1676
Seoul 7007964 5379867 2722215366 943
Gyeongsangnam 3432930 2193482 1189481310 489
Busan 2348753 1985125 971633520 430
Jeollabuk 2360542 1405530 1114863500 352
Incheon 1822653 1186865 664467380 300
Chungcheongnam 1941777 1054556 722603535 389
Gyeongsangbuk 1787252 1029986 657905670 293
Jeollanam 1603575 921384 583900035 337
Chungcheongbuk 1346886 914052 505361170 260
Gwangju 1601091 856766 586752990 346
Ulsan 1172909 802806 500926171 188
Daegu 1574325 794620 673183961 219
Gangwon 1175465 747614 554448010 224
Daejeon 1459281 665219 577268177 244
Jeju 714530 329891 332226496 150
Sejong 394395 227268 87407550 59
In [30]:
#도서예산 별 내림차순
df_sorted_budget = grouped_by_region.sort_values(by=['budget'], ascending=False)
df_sorted_budget
Out[30]:
administrativebook_countvisitedbudgetlib_count182137155113412601610149
Gyeonggi 11534961 7476915 4784425986 1676
Seoul 7007964 5379867 2722215366 943
Gyeongsangnam 3432930 2193482 1189481310 489
Jeollabuk 2360542 1405530 1114863500 352
Busan 2348753 1985125 971633520 430
Chungcheongnam 1941777 1054556 722603535 389
Daegu 1574325 794620 673183961 219
Incheon 1822653 1186865 664467380 300
Gyeongsangbuk 1787252 1029986 657905670 293
Gwangju 1601091 856766 586752990 346
Jeollanam 1603575 921384 583900035 337
Daejeon 1459281 665219 577268177 244
Gangwon 1175465 747614 554448010 224
Chungcheongbuk 1346886 914052 505361170 260
Ulsan 1172909 802806 500926171 188
Jeju 714530 329891 332226496 150
Sejong 394395 227268 87407550 59
In [31]:
#도서관 수별 내림차순
df_sorted_lib = grouped_by_region.sort_values(by=['lib_count'], ascending=False)
df_sorted_lib
Out[31]:
administrativebook_countvisitedbudgetlib_count182715134121131660510149
Gyeonggi 11534961 7476915 4784425986 1676
Seoul 7007964 5379867 2722215366 943
Gyeongsangnam 3432930 2193482 1189481310 489
Busan 2348753 1985125 971633520 430
Chungcheongnam 1941777 1054556 722603535 389
Jeollabuk 2360542 1405530 1114863500 352
Gwangju 1601091 856766 586752990 346
Jeollanam 1603575 921384 583900035 337
Incheon 1822653 1186865 664467380 300
Gyeongsangbuk 1787252 1029986 657905670 293
Chungcheongbuk 1346886 914052 505361170 260
Daejeon 1459281 665219 577268177 244
Gangwon 1175465 747614 554448010 224
Daegu 1574325 794620 673183961 219
Ulsan 1172909 802806 500926171 188
Jeju 714530 329891 332226496 150
Sejong 394395 227268 87407550 59
In [33]:
# 장서수 기준 내림차순 정렬된 행정구역
df_sorted_book = grouped_by_region.sort_values(by='book_count', ascending=False)['administrative']

# 방문자수 기준 내림차순 정렬된 행정구역
df_sorted_visited = grouped_by_region.sort_values(by='visited', ascending=False)['administrative']

# 도서예산 기준 내림차순 정렬된 행정구역
df_sorted_budget = grouped_by_region.sort_values(by='budget', ascending=False)['administrative']

# 도서관 수 기준 내림차순 정렬된 행정구역
df_sorted_lib = grouped_by_region.sort_values(by='lib_count', ascending=False)['administrative']

# 새로운 데이터프레임 생성
df_result = pd.DataFrame({
    'book_count': df_sorted_book.values,
    'visited': df_sorted_visited.values,
    'budget': df_sorted_budget.values,
    'lib_count': df_sorted_lib.values
})

df_result
Out[33]:
book_countvisitedbudgetlib_count012345678910111213141516
Gyeonggi Gyeonggi Gyeonggi Gyeonggi
Seoul Seoul Seoul Seoul
Gyeongsangnam Gyeongsangnam Gyeongsangnam Gyeongsangnam
Jeollabuk Busan Jeollabuk Busan
Busan Jeollabuk Busan Chungcheongnam
Chungcheongnam Incheon Chungcheongnam Jeollabuk
Incheon Chungcheongnam Daegu Gwangju
Gyeongsangbuk Gyeongsangbuk Incheon Jeollanam
Jeollanam Jeollanam Gyeongsangbuk Incheon
Gwangju Chungcheongbuk Gwangju Gyeongsangbuk
Daegu Gwangju Jeollanam Chungcheongbuk
Daejeon Ulsan Daejeon Daejeon
Chungcheongbuk Daegu Gangwon Gangwon
Gangwon Gangwon Chungcheongbuk Daegu
Ulsan Daejeon Ulsan Ulsan
Jeju Jeju Jeju Jeju
Sejong Sejong Sejong Sejong

장서수, 방문자수, 도서예산, 도서관 수 기준으로 다시 데이터프레임을 짠 후, 이를 출력했다.

  1. 1-3위까지는 경기, 서울, 경남 순으로 일정한 것으로 보인다. 이는, 모두 숫자의 크기 나열 순이므로 인구 수와 비례하는 경향이 있다. 실제로, 2019년 인구를 보면 경기도는 1324만명, 서울은 973만명, 경남은 부산보다 5만 적은 336만으로 인구 수를 따라가는 경향이 보인다. 부산이 경남보다 5만 앞서지만 3위를 하지 못한 이유는, 부산은 노인이 많고, 잦은 어업 활동으로 인하여 육지에서 활발한 활동 가능 인구 자체가 좀 적기 때문으로 예상한다.
  2. 제주와 세종 역시 가장 밑 순위에 나란히 있다. 이 역시도 제주 67만, 세종 34만으로 가장 적은 인구의 도시이기 때문이다.
  3. 대전은 장서수, 도서예산, 도서관 수 모두 12위이지만, 방문자 수가 15위로 가장 간격이 벌어져 있다. 이는 <2019년 국민 도서실태 조사>에서 지역별 독서 지표에서, 연간 독서율이 39.3%로 다른 곳보다 현저히 떨어지는 것을 볼 수 있다.
  4. 반대로, 울산은 장서수, 예산, 도서관 수 모두 15위지만 방문자 수는 12위를 기록하고 있다. 정확히 대전과 울산의 순위가 디커플링되고 있다. 이 역시 <2019년 국민 도서실태 조사>에서 지역별 독서 지표를 보면, 연간 독서율이 58.3%로 꽤 준수한 순위에 위치해있다.
  5. 가장 아래 순위인 제주와 세종은 <2019년 국민 도서실태 조사>에서 연간독서량을 보면 각각 63.5%, 53.4%로 준수한 순위에 위치해 있다. 이 곳은 작은도서관의 수에서는 영향을 별로 받지 않는다는 것을 알 수 있다.
In [63]:
print(df_result)
        book_count         visited          budget       lib_count
0         Gyeonggi        Gyeonggi        Gyeonggi        Gyeonggi
1            Seoul           Seoul           Seoul           Seoul
2    Gyeongsangnam   Gyeongsangnam   Gyeongsangnam   Gyeongsangnam
3        Jeollabuk           Busan       Jeollabuk           Busan
4            Busan       Jeollabuk           Busan  Chungcheongnam
5   Chungcheongnam         Incheon  Chungcheongnam       Jeollabuk
6          Incheon  Chungcheongnam           Daegu         Gwangju
7    Gyeongsangbuk   Gyeongsangbuk         Incheon       Jeollanam
8        Jeollanam       Jeollanam   Gyeongsangbuk         Incheon
9          Gwangju  Chungcheongbuk         Gwangju   Gyeongsangbuk
10           Daegu         Gwangju       Jeollanam  Chungcheongbuk
11         Daejeon           Ulsan         Daejeon         Daejeon
12  Chungcheongbuk           Daegu         Gangwon         Gangwon
13         Gangwon         Gangwon  Chungcheongbuk           Daegu
14           Ulsan         Daejeon           Ulsan           Ulsan
15            Jeju            Jeju            Jeju            Jeju
16          Sejong          Sejong          Sejong          Sejong

각 기준별, 도시 순위를 새로 만든 데이터프레임을 시각화 그래프 그리기 편하게, 영어로 바꿔주었다.

6) 데이터 시각화

이제, 각 컬럼(장서 수, 방문자수, 도서예산, 도서관 수) 기준으로 시각화 그래프를 그려보았다.

In [84]:
import pandas as pd
import matplotlib.pyplot as plt


# 순위 컬럼 추가
df_result['rank'] = range(1, len(df_result) + 1)

# 시각화
plt.figure(figsize=(20, 20))
for col in df_result.columns[:-1]:  # rank 컬럼 제외
    plt.plot(df_result[col], df_result['rank'], marker='o', label=col)

plt.title('Rankings of Locations')
plt.xlabel('Locations')
plt.ylabel('Rank')
plt.yticks(range(1, len(df_result) + 1))
plt.legend()
plt.grid(True)
plt.tight_layout()

plt.show()

위의 df_result를 보기 좋게 랭크함수를 이용하여 시각화해 보았다.

7) 데이터 또는 분석 과정 차별화 포인트

데이터 분석을 어떤 방식으로 할 것인가 먼저 고민하였다. 작은 도서관에 대한 컬럼들(장서수, 예산, 도서관수, 방문자수 등)이 있으니 어떤 식으로 활용하는 것이 재미있겠는가 먼저 생각했다. 전국에 작은 도서관들이 많다는 것은 알고 있었으나, 이 정도로 많으리라고는 생각 못했다. 하나의 작은 도서관을 보면 이 도서관이 얼마나 사람들에게 영향을 끼치겠나 생각도 들었으나 데이터를 모아보니 모든 컬럼들이 꽤 높은 숫자를 나타내고 있었다. 예산 역시 꽤 높은 숫자를 차지하고 있었다. 객관적으로 바라보면 높은 숫자지만, 주관적으로 바라봤을 때는 도서관의 숫자가 저렇게 많은데 예산이 낮아서 안타까운 부분도 있었다.

작은 도서관의 존재가 빛을 발하려면, 방문하는 시민들의 수가 많아야 한다. 그렇기 때문에 지역별 도서관의 수와 방문자수를 비교하는 것을 우선으로 두었다. 그러나 단순히 도서관의 수와 방문자수를 비교하는 것은 어쩌면 뻔한 결과를 나타낼 수 있다. 인구가 많은 도시, 도서관의 수가 많은 도시가 방문자가 많은 것은 당연한 결과이다. 물론 예외가 있을 수 있지만 말이다. 그래서, 분석 과정 차별화 포인트로써 문화체육관광부에서 만든 전국 독서지표 자료를 활용하였다. 이는 각 지역별로 비율을 나타내었기 때문에, 절대적 숫자인 도서관수, 방문자수와 개별적 비율인 독서율, 독서량, 방문율 등을 함께 활용하였다.

8) 데이터 분석 수업을 마감하며

서론에서도 썼지만, 빅데이터분석을 배우기 전에는 막연하게 어렵다고 생각을 하였다. 어마어마한 양을 다루기도 어려울 것이며, 문제가 있는 부분을 찾는 것도 한세월이 걸리고, 그 많은 데이터를 어느 방향으로 분석하여 활용할 것인지 감이 안 잡히기도 하였다. 어떻게 데이터를 다루고, 꼬고, 만져주고, 안아주고, 이뻐해 줄 수 있을까. 우리같이 멍청한 일반인들을 위해 세계의 많은 똑똑한 분들이 빅데이터를 분석하기 쉽게 많은 도구들을 만들어 두었다. 심지어 빅데이터를 정확한 근거와 체계적인 단계를 거쳐서 만들어도 두었다. 우리는 내가 무엇을 원하는지만 고민하면, 내가 보기 좋게 만들어낼 수 있다.

나는 엄마의 20년 넘는 취미생활이자 직업인 사립도서관의 운영이 다른 시민들에게 도움이 되는가 궁금했다. 또한, 전국에 사립 작은 도서관들이 많다는 것을 알고 있었으나 이 데이터들이 모아져 있는 게 있을까? 이 데이터들이 있다면 활용을 할 수 있을까? 호기심으로 분석해 보기 시작했다. 일상에서 찾는 호기심에서 시작해야 분석할 때 동기부여가 된다는 것도 느낄 수 있었다. 사실 작은 도서관들이 전국에 많은 숫자로 퍼져 있다지만 공공도서관에 비하면 방문수가 낮은 숫자이다. 그러나 작은 도서관의 역할은 단순한 독서가 아니라 독서모임, 다양한 시민 프로그램, 아동 돌봄, 꿈의 학교, 쉼터, 놀이터 등 시민사회적인 역할을 담당하고 있다. 모쪼록, 재밌는 연구 주제였으며 유익했다.

빅데이터분석개론 수업을 들으면서 빅데이터가 재미있을 수 있구나 생각이 들어 학기 중 ADSP와 SQLD 자격증 역시 준비해서 따보았다. 시험 준비 과정에서 수업에 배웠던 내용들이 정말 많이 나오길래 도움이 많이 되었다. ADSP는 합격을 했으며 SQLD는 결과를 기다리고 있으나 합격할 것 같다. 여러 가지를 얻어갔으니 충분히 가치 있었던 수업이라 생각한다. 감사합니다.