티스토리 뷰

1단원

파이썬으로 데이터 주무르기라는 책을 보고 데이터 분석과정을 따라해보고자 한다. 이 책은 이 분야로 이끌어준 친한 동생이 추천해준 소중한 책이다.
처음에는 이해가 안되어 몇 개 따라해보다 말았는데, 이제는 이해 할 수 있을 정도가 되어 하나하나 따라해보며 과정을 곱씹어보려 한다.

이 책은 총 8개의 대단원으로 이루어져 있고, 각 대단원마다는 조금씩 관련이 있는것 같다.
지금 진행하는 단원은 다음과 같이 구성되어 있고, 시간날때마다 천천히 정리해보겠다.

1단원 서울시 구별 CCTV현황 분석

    1. CCTV 현황과 인구 현황 데이터 구하기
    1. 파이썬에서 텍스트 파일과 엑셀 파일을 읽기 -pandas
    1. pandas 기초 익히기
    1. pandas를 이용해서 CCTV와 인구 현황 데이터 파악하기
    1. pandas 고급기능 - 두 DataFrame 병합하기
    1. CCTV 데이터와 인구 현황 데이터를 합치고 분석하기
    1. 파이썬의 대표 시각화 도구 - Matplotlib
    1. CCTV 현황 그래프로 분석하기

1. CCTV 현황과 인구 현황 데이터 구하기

https://github.com/PinkWink/DataScience/tree/master/data
파이썬으로 데이터 주무르기 깃허브. 책에 나온 코드들과 텍스트 파일 및 엑셀 파일을 받을 수 있다.

2. 파이썬에서 텍스트 파일과 엑셀 파일 읽기

In [1]:
import pandas as pd
In [2]:
CCTV_Seoul = pd.read_csv('pydata/01. CCTV_in_Seoul.csv', encoding='utf-8') # UTF-8로 인코딩 되어있는 데이터를 불러온다.
CCTV_Seoul.head() # 5행만 보여주시오
Out[2]:
기관명 소계 2013년도 이전 2014년 2015년 2016년
0 강남구 2780 1292 430 584 932
1 강동구 773 379 99 155 377
2 강북구 748 369 120 138 204
3 강서구 884 388 258 184 81
4 관악구 1496 846 260 390 613
In [3]:
CCTV_Seoul.columns # 컬럼의 이름이 반환된다.
Out[3]:
Index(['기관명', '소계', '2013년도 이전', '2014년', '2015년', '2016년'], dtype='object')
In [4]:
CCTV_Seoul.columns[0] # 첫번째 컬럼의 이름을 반환한다.
Out[4]:
'기관명'
In [5]:
# 첫번째 컬럼의 이름을 '구별'로 바꾸겠다.
CCTV_Seoul.rename(columns={CCTV_Seoul.columns[0]:'구별'}, inplace=True)
CCTV_Seoul.head()
Out[5]:
구별 소계 2013년도 이전 2014년 2015년 2016년
0 강남구 2780 1292 430 584 932
1 강동구 773 379 99 155 377
2 강북구 748 369 120 138 204
3 강서구 884 388 258 184 81
4 관악구 1496 846 260 390 613
In [6]:
# 두 번째 받은 엑셀 파일을 읽자.
pop_Seoul = pd.read_excel('pydata/01. population_in_Seoul.xls', encoding='utf-8')
pop_Seoul.head()
Out[6]:
기간 자치구 세대 인구 인구.1 인구.2 인구.3 인구.4 인구.5 인구.6 인구.7 인구.8 세대당인구 65세이상고령자
0 기간 자치구 세대 합계 합계 합계 한국인 한국인 한국인 등록외국인 등록외국인 등록외국인 세대당인구 65세이상고령자
1 기간 자치구 세대 남자 여자 남자 여자 남자 여자 세대당인구 65세이상고령자
2 2017.1/4 합계 4202888 10197604 5000005 5197599 9926968 4871560 5055408 270636 128445 142191 2.36 1321458
3 2017.1/4 종로구 72654 162820 79675 83145 153589 75611 77978 9231 4064 5167 2.11 25425
4 2017.1/4 중구 59481 133240 65790 67450 124312 61656 62656 8928 4134 4794 2.09 20764

읽어오긴 했는데 형태가 좀 이상하다. 위에 2줄이 컬럼명에 있어야 하는데...?

In [7]:
# header=2로 하여 3줄을 읽도록 하자. 
#엑셀 컬럼을 나타내는 B, D, G, J, N 열만 읽도록 parse_cols='B,D,G,J,N' 옵션을 넣는다.(usecols로 바뀜)
pop_Seoul = pd.read_excel('pydata/01. population_in_Seoul.xls', 
                           header=2,
                           usecols = 'B, D, G, J, N',
                           encoding='utf-8')
pop_Seoul.head()
Out[7]:
자치구 계.1 계.2 65세이상고령자
0 합계 10197604.0 9926968.0 270636.0 1321458.0
1 종로구 162820.0 153589.0 9231.0 25425.0
2 중구 133240.0 124312.0 8928.0 20764.0
3 용산구 244203.0 229456.0 14747.0 36231.0
4 성동구 311244.0 303380.0 7864.0 39997.0
In [8]:
# 컬럼명이 마음에 안들어 바꾸자!
pop_Seoul.rename(columns={pop_Seoul.columns[0]: '구별',
                          pop_Seoul.columns[1]: '인구수',
                          pop_Seoul.columns[2]: '한국인',
                          pop_Seoul.columns[3]: '외국인',
                          pop_Seoul.columns[4]: '고령자'}, inplace=True)
pop_Seoul.head()
Out[8]:
구별 인구수 한국인 외국인 고령자
0 합계 10197604.0 9926968.0 270636.0 1321458.0
1 종로구 162820.0 153589.0 9231.0 25425.0
2 중구 133240.0 124312.0 8928.0 20764.0
3 용산구 244203.0 229456.0 14747.0 36231.0
4 성동구 311244.0 303380.0 7864.0 39997.0

3.pandas 기초 익히기

(1) Series와 DataFrame

In [9]:
import pandas as pd
import numpy as np
In [10]:
# Series는 판다스 데이터 유형 중 기초이다.
# 대괄호를 이용하여 list를 만든 후 pd.Series 명령어를 이용하여 만들어 주었다.
s = pd.Series([1,3,5,np.nan,6,8])
s
Out[10]:
0    1.0
1    3.0
2    5.0
3    NaN
4    6.0
5    8.0
dtype: float64
In [11]:
# date range를 이용하여 기준날짜로 부터 6일간의 날짜를 구할 수 있다.
dates = pd.date_range('20130101', periods=6)
dates
Out[11]:
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
               '2013-01-05', '2013-01-06'],
              dtype='datetime64[ns]', freq='D')
In [12]:
# 6행 4열의 random 변수를 만들고 컬럼은 A,B,C,D로 지정한다.
# 인덱스를 위에서 구해준 날짜로 지정해준다.
df=pd.DataFrame(np.random.randn(6,4), index=dates, columns=['A','B','C','D'])
df
Out[12]:
A B C D
2013-01-01 0.090582 0.835024 -1.024241 -1.222541
2013-01-02 1.057344 -1.580570 0.512993 -0.758468
2013-01-03 -0.786472 -0.791502 -0.399722 0.806766
2013-01-04 -1.851722 -1.993739 -0.114528 -0.554944
2013-01-05 -0.218675 -1.363616 -0.048664 -0.464271
2013-01-06 -0.263567 0.076818 1.682586 -0.461049
In [13]:
# 3행까지만 볼래!
df.head(3) 
Out[13]:
A B C D
2013-01-01 0.090582 0.835024 -1.024241 -1.222541
2013-01-02 1.057344 -1.580570 0.512993 -0.758468
2013-01-03 -0.786472 -0.791502 -0.399722 0.806766
In [14]:
#인덱스를 보여줘!
df.index 
Out[14]:
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
               '2013-01-05', '2013-01-06'],
              dtype='datetime64[ns]', freq='D')
In [15]:
#컬럼명을 보여줘!
df.columns 
Out[15]:
Index(['A', 'B', 'C', 'D'], dtype='object')
In [16]:
#안에 들어가는 내용들을 확인 가능
df.values 
Out[16]:
array([[ 0.09058215,  0.83502438, -1.02424053, -1.22254095],
       [ 1.05734359, -1.58056973,  0.51299258, -0.75846838],
       [-0.7864717 , -0.79150223, -0.3997216 ,  0.80676626],
       [-1.85172165, -1.99373906, -0.11452781, -0.55494359],
       [-0.21867514, -1.36361611, -0.0486638 , -0.46427052],
       [-0.26356678,  0.07681802,  1.68258611, -0.46104932]])
In [17]:
# 데이터 프레임의 개요를 알 수 있다.
df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 6 entries, 2013-01-01 to 2013-01-06
Freq: D
Data columns (total 4 columns):
A    6 non-null float64
B    6 non-null float64
C    6 non-null float64
D    6 non-null float64
dtypes: float64(4)
memory usage: 240.0 bytes
In [18]:
# 통계적 개요를 확인할 수 있다.
df.describe()
Out[18]:
A B C D
count 6.000000 6.000000 6.000000 6.000000
mean -0.328752 -0.802931 0.101404 -0.442418
std 0.963578 1.076485 0.922702 0.675637
min -1.851722 -1.993739 -1.024241 -1.222541
25% -0.655745 -1.526331 -0.328423 -0.707587
50% -0.241121 -1.077559 -0.081596 -0.509607
75% 0.013268 -0.140262 0.372578 -0.461855
max 1.057344 0.835024 1.682586 0.806766
In [19]:
# B열을 기준으로 내림차순으로 정렬했다. Default 값은 asending=True로 오름차순
df.sort_values(by='B', ascending=False)
Out[19]:
A B C D
2013-01-01 0.090582 0.835024 -1.024241 -1.222541
2013-01-06 -0.263567 0.076818 1.682586 -0.461049
2013-01-03 -0.786472 -0.791502 -0.399722 0.806766
2013-01-05 -0.218675 -1.363616 -0.048664 -0.464271
2013-01-02 1.057344 -1.580570 0.512993 -0.758468
2013-01-04 -1.851722 -1.993739 -0.114528 -0.554944
In [20]:
# 컬럼에 해당하는 Series를 보여준다.
df['A']
Out[20]:
2013-01-01    0.090582
2013-01-02    1.057344
2013-01-03   -0.786472
2013-01-04   -1.851722
2013-01-05   -0.218675
2013-01-06   -0.263567
Freq: D, Name: A, dtype: float64

(2) loc

In [21]:
# 원하는 행의 범위를 지정해서 볼 수 있다.
df[0:3]
Out[21]:
A B C D
2013-01-01 0.090582 0.835024 -1.024241 -1.222541
2013-01-02 1.057344 -1.580570 0.512993 -0.758468
2013-01-03 -0.786472 -0.791502 -0.399722 0.806766
In [22]:
# 인덱스를 이용해 행의 범위를 지정할수도 있다.
df['20130102':'20130104']
Out[22]:
A B C D
2013-01-02 1.057344 -1.580570 0.512993 -0.758468
2013-01-03 -0.786472 -0.791502 -0.399722 0.806766
2013-01-04 -1.851722 -1.993739 -0.114528 -0.554944
In [23]:
# 특정 인덱스의 데이터만 보고 싶다면 df.loc 명령을 사용해봐!
df.loc[dates[1]]
Out[23]:
A    1.057344
B   -1.580570
C    0.512993
D   -0.758468
Name: 2013-01-02 00:00:00, dtype: float64
In [24]:
# A, B열의 모든 행을 보고 싶다면 ?!
df.loc[:,['A','B']]
Out[24]:
A B
2013-01-01 0.090582 0.835024
2013-01-02 1.057344 -1.580570
2013-01-03 -0.786472 -0.791502
2013-01-04 -1.851722 -1.993739
2013-01-05 -0.218675 -1.363616
2013-01-06 -0.263567 0.076818
In [25]:
# 행과 열의 범위를 동시에 지정해볼까?
df.loc['20130102':'20130104',['A','B']]
Out[25]:
A B
2013-01-02 1.057344 -1.580570
2013-01-03 -0.786472 -0.791502
2013-01-04 -1.851722 -1.993739
In [26]:
# 2013년 1월 2일의 A, B 컬럼의 내용을 보자
df.loc['20130102',['A','B']]
Out[26]:
A    1.057344
B   -1.580570
Name: 2013-01-02 00:00:00, dtype: float64
In [27]:
# dates[0]에 맞는 날짜인 2013년 1월 1일의 A컬럼 데이터 확인
df.loc[dates[0],'A']
Out[27]:
0.0905821450180709

(3) iloc

In [28]:
# 행과 열의 번호를 이용하여 데이터에 바로 접근
df.iloc[3]
Out[28]:
A   -1.851722
B   -1.993739
C   -0.114528
D   -0.554944
Name: 2013-01-04 00:00:00, dtype: float64
In [29]:
# 3번부터 5번째 앞까 행과 0번부터 1번까지 열의 데이터를 가져오기
df.iloc[3:5,0:2]
Out[29]:
A B
2013-01-04 -1.851722 -1.993739
2013-01-05 -0.218675 -1.363616
In [30]:
# 범위가 아니라 콤마를 이용해서 행과 열을 지정할 수도 있다.
df.iloc[[1,2,4],[0,2]]
Out[30]:
A C
2013-01-02 1.057344 0.512993
2013-01-03 -0.786472 -0.399722
2013-01-05 -0.218675 -0.048664
In [31]:
# : 는 전체범위를 의미한다. 모든 행을 출력!
df.iloc[:,1:3]
Out[31]:
B C
2013-01-01 0.835024 -1.024241
2013-01-02 -1.580570 0.512993
2013-01-03 -0.791502 -0.399722
2013-01-04 -1.993739 -0.114528
2013-01-05 -1.363616 -0.048664
2013-01-06 0.076818 1.682586
In [32]:
# 이번에는 모든 열을 출력!
df.iloc[1:3,:]
Out[32]:
A B C D
2013-01-02 1.057344 -1.580570 0.512993 -0.758468
2013-01-03 -0.786472 -0.791502 -0.399722 0.806766

(4) 조건문

In [33]:
df
Out[33]:
A B C D
2013-01-01 0.090582 0.835024 -1.024241 -1.222541
2013-01-02 1.057344 -1.580570 0.512993 -0.758468
2013-01-03 -0.786472 -0.791502 -0.399722 0.806766
2013-01-04 -1.851722 -1.993739 -0.114528 -0.554944
2013-01-05 -0.218675 -1.363616 -0.048664 -0.464271
2013-01-06 -0.263567 0.076818 1.682586 -0.461049
In [34]:
# A컬럼에서 0보다 큰 행만 출력하시오!
df[df.A>0]
Out[34]:
A B C D
2013-01-01 0.090582 0.835024 -1.024241 -1.222541
2013-01-02 1.057344 -1.580570 0.512993 -0.758468
In [35]:
# 데이터 자체에 조건을 걸면 만족하지 않은 곳은 NaN 처리된다.
df[df>0]
Out[35]:
A B C D
2013-01-01 0.090582 0.835024 NaN NaN
2013-01-02 1.057344 NaN 0.512993 NaN
2013-01-03 NaN NaN NaN 0.806766
2013-01-04 NaN NaN NaN NaN
2013-01-05 NaN NaN NaN NaN
2013-01-06 NaN 0.076818 1.682586 NaN
In [36]:
# 데이터의 원본은 바꾸고 싶지 않을때 copy 명령어를 사용한다.
df2 = df.copy()
In [37]:
# E 컬럼을 새롭게 추가한다.
df2['E'] = ['one', 'one', 'two', 'three', 'four', 'three']
df2
Out[37]:
A B C D E
2013-01-01 0.090582 0.835024 -1.024241 -1.222541 one
2013-01-02 1.057344 -1.580570 0.512993 -0.758468 one
2013-01-03 -0.786472 -0.791502 -0.399722 0.806766 two
2013-01-04 -1.851722 -1.993739 -0.114528 -0.554944 three
2013-01-05 -0.218675 -1.363616 -0.048664 -0.464271 four
2013-01-06 -0.263567 0.076818 1.682586 -0.461049 three
In [38]:
# isin 명령을 이용해 'two'와 'four'가 있는지 조건을 확인.
df2['E'].isin(['two','four'])
Out[38]:
2013-01-01    False
2013-01-02    False
2013-01-03     True
2013-01-04    False
2013-01-05     True
2013-01-06    False
Freq: D, Name: E, dtype: bool
In [39]:
# 조건에 맞는 행만 추출
df2[df2['E'].isin(['two','four'])]
Out[39]:
A B C D E
2013-01-03 -0.786472 -0.791502 -0.399722 0.806766 two
2013-01-05 -0.218675 -1.363616 -0.048664 -0.464271 four

(5) cumsum

In [40]:
df
Out[40]:
A B C D
2013-01-01 0.090582 0.835024 -1.024241 -1.222541
2013-01-02 1.057344 -1.580570 0.512993 -0.758468
2013-01-03 -0.786472 -0.791502 -0.399722 0.806766
2013-01-04 -1.851722 -1.993739 -0.114528 -0.554944
2013-01-05 -0.218675 -1.363616 -0.048664 -0.464271
2013-01-06 -0.263567 0.076818 1.682586 -0.461049
In [41]:
# 누적합을 구한다.
df.apply(np.cumsum)
Out[41]:
A B C D
2013-01-01 0.090582 0.835024 -1.024241 -1.222541
2013-01-02 1.147926 -0.745545 -0.511248 -1.981009
2013-01-03 0.361454 -1.537048 -0.910970 -1.174243
2013-01-04 -1.490268 -3.530787 -1.025497 -1.729187
2013-01-05 -1.708943 -4.894403 -1.074161 -2.193457
2013-01-06 -1.972510 -4.817585 0.608425 -2.654506

(6) lambda

In [42]:
# 최대값과 최소값의 차이를 구한다.
df.apply(lambda x: x.max() - x.min())
Out[42]:
A    2.909065
B    2.828763
C    2.706827
D    2.029307
dtype: float64
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함