기본 콘텐츠로 건너뛰기

Python 데이터 분석

탐색적 데이터 분석
- 범주형(Categorical) : 10대, 20대, 남, 여
- 연속형(수치형) : 

범주형

빈도분석
<code>
tips['sex'].value_counts() # Male:157,Female:87,Name:sex,dtype:Int64
</code>

교차분석
pd.crosstab(tips['sex'],tips['day'],margins=True) # margins : 
'''
day         Thur Fri Sat Sun All
sex
Male         30 10 59 58 157
Female 32 9 28 18 87
All         62 19 87 76 244
'''

전체 빈도 비율
pd.crosstab(tips['sex'],tips['day']).apply(lambda r: r/len(tips), axis=1) # axis=1 : 열 방향
'''
day         Thur Fri Sat Sun
sex
Male         0.122951 0.040984 0.241803 0.237705 # 30 / 244, 10 / 244, 59 / 244, 58 / 244
Female 0.131148 0.036885 0.114754 0.073770 # 32 / 244, 9 / 244, 28 / 244, 18 / 244
'''

apply()
import pandas as pd
import numpy as np

df = pd.DataFrame(np.arange(12).reshape(3,4))
'''
0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
'''
df.apply(lambda r: print(r), axis=0) # r은 각 열에 있는 행
'''
0, 4, 8
1, 5, 9
2, 6, 10
3, 7, 11
'''
df.apply(lambda r: print(r), axis=1) # r은 각 행에 있는 열
'''
0, 1, 2, 3
4, 5, 6, 7
8, 9, 10, 11
'''
df.apply(lambda r: r/len(df), axis=0)
'''
0         1         2         3
0 0.000000 0.333333 0.666667 1.000000
1 1.333333 1.666667 2.000000 2.333333
2 2.666667 3.000000 3.333333 3.666667
'''

# df로부터 3번째 컬럼을 추출한다
# 짝수 0, 홀수 1
# 0, 1으로 구성된 시리즈를 대상을 빈도분석을 해보세요
# df.apply() : 익명함수로 전달되는 데이터는 시리즈인데, 행일수도 열일수도 있다
# series.apply() : 익명함수로 전달되는 데이터는 스칼라값 한개이다
df.apply(lambda r : r%2, axis=1)
'''
0 1 2 3
0 0 1 0 1
1 0 1 0 1
2 0 1 0 1
'''
df[3].apply(lambda r : r%2).value_counts()
'''
1    3
Name: 3, dtype: int64
'''

벡터연산
arr = np.arange(5) # array([0, 1, 2, 3, 4])
type(arr) # numpy.ndarray
arr2 = arr/2 # Vector / Scala
arr2 # array([0. , 0.5, 1. , 1.5, 2. ])

정규분포(Normal Distribution)
arr = np.random.normal(5,2,1000).astype(int) # normal : 정규분포, 5 : 평균, 2 : 표준편차, 1000 : 값의 갯수
pd.DataFrame(arr).value_counts()
'''
 5     199
 4     193
 6     138
 3     135
 7     108
 2      90
 1      52
 8      42
 9      18
 0      16
 10      7
-1       2
dtype: int64
'''
import matplotlib.pyplot as plt
plt.hist(arr)
plt.show()

CSV 파일 교차분석
# employees.csv를 로드하여 emp_df을 생성한다
# gender, job_title 간의 교차분석
import pandas as pd
emp_df = pd.read_csv('employees.csv',header=None,index_col=0,names=['id','gender','first_name','phone','job_title'])
display(emp_df)
'''
gender first_name phone job_title
id
1 male Jose 1-971-533-4552x1542
Machine Learning Engineer
2 male Douglas 881.633.0107
DevOps Engineer
3 female Sherry 001-966-861-0065x493 Project Manager
4 male Charles 001-574-564-4648 Project Manager
5 female Sharon 5838355842 HR Manager
... ... ... ... ...
316 female Michelle 401.041.6802 Web Developer
317 male Steven 1-584-489-5663x896 Web Developer
318 male Kevin 001-511-226-4416x83410 Web Developer
319 male Adam 1-426-702-6363x565 Web Developer
320 male Danny (871)098-2647x80448 Web Developer
'''
display(pd.crosstab(emp_df['gender'],emp_df['job_title']))
'''
job_title Designer DevOps Engineer HR Manager Machine Learning Engineer Mobile Developer Project Manager Tester Web Developer
gender
female 7 16 7 14 40 3 8 51
male 8 20 3 10 50 2 12 69
'''
display(pd.crosstab(emp_df['gender'],emp_df['job_title']).apply(lambda r : r/len(emp_df), axis=1))
'''
job_title Designer DevOps Engineer HR Manager Machine Learning Engineer Mobile Developer Project Manager Tester Web Developer
gender
female 0.021875 0.05 0.021875 0.04375 0.125 0.009375 0.025 0.159375
male 0.025 0.0625 0.009375 0.03125 0.15625 0.00625 0.0375 0.215625
'''

균등분포(Uniform Distribution)

카이제곱(Chi-Square)
- crosstab() 리턴한 분할표를 사용함
- 카이제곱 검정(Chi-Square Test)
- 두 범주형 변수가 서로 독립적인지 검사
- p-value : 0.5보다 작으면 귀무가설을 기각함, 대립가설에 의미가 있다
- 귀무가설 : 두 범주형 변수는 서로 독립적이다
- 대립가설 : 두 범주형 변수는 독립적이지 않다
contingency = pd.crosstab(emp_df['gender'],emp_df['job_title'])
# 분할표
display(contingency)
'''
job_title Designer DevOps Engineer HR Manager Machine Learning Engineer Mobile Developer Project Manager Tester Web Developer
gender
female 7 16 7 14 40 3 8 51
male 8 20 3 10 50 2 12 69
'''
from scipy.stats import chi2_contingency
c, p, dof, expected = chi2_contingency(contingency)
display(p) # 0.6381856628
p-value가 0.5보다 작지 않기 때문에 귀무가설이 의미가 있다

연속형

평균
np.arange(10).mean() # 4.5

중위수
np.random.seed(5) # 같은 무작위 숫자가 나오게 설정
ser = pd.Series(np.random.randint(1, 20, 10)).sort_values()
list(ser) # [4, 5, 7, 8, 9, 10, 15, 16, 17, 17]
ser.median() # 9.5, 정렬된 숫자의 가운데 숫자, 짝수면 2개의 평균

분산(Variance) : ((평균 - 각 원소)^2)의 총합 / n
# 분산 구하기(표본 통계)
ser.var() # 25.28888888888889
# 직접 분산 구하기(모수 통계)
((ser.mean() - ser)**2).sum() / len(ser) # 22.76
# 직접 분산 구하기(표본 통계)
# 자유도 : n-1
((ser.mean() - ser)**2).sum() / (len(ser) - 1) # 25.28888888888889

표준편차 : √분산
ser.std() # 5.028805910838963
# 분산 값을 이용해서 표준편차 구하기
np.sqrt(ser.var()) # 5.028805910838963
# 저수준으로 표준편차 구하기
variance = ((ser.mean() - ser)**2).sum() / (len(ser) - 1) # 25.28888888888889
standardDeviation = variance**(1/2) # 5.028805910838963

기술통계
# 기술통계
ser.describe()
'''
count    10.000000 # 갯수
mean     10.800000 # 평균
std       5.028806 # 표준편차
min       4.000000 # 
25%       7.250000 # 1사분위수 : 25% 위치에 있는 수
50%       9.500000 # 2사분위수 : 50% 위치에 있는 중위수
75%      15.750000 # 3사분위 수 : 75% 위치에 있는 수
max      17.000000 # 
dtype: float64
'''
ser.describe().index # Index(['count', 'mean', 'std', 'min', '25%', '50%', '75%', 'max'], dtype='object')
ser.describe()['25%'] # 7.25

사분위수
#중위수
ser.quantile() # 9.5
ser.quantile(.75) # 3사분위수
ser.quantile([0.25,0.5,0.75]) # 1사분위수,2사분위수,3사분위수
'''
0.25     7.25 # 25%, 1사분위수 Q1
0.50     9.50 # 50%, 2사분위수, Q2, 중위수
0.75    15.75 # 75%, 3사분위수, Q3
dtype: float64
'''
25% Q1
50% Q2
75% Q3
사분위수 범위(IQR) : Q3 - Q1 거리
정상치 : Q1 - IQR * 1.5 ~ Q3 + IQR * 1.5
이상치 : 정상치를 벗어난 범위

사분위수 구하기
p1 = (len(ser)-1) / 4 # 1.25 지점에 1사분위수가 위치해있다
p2 = ((len(ser)-1) / 4)*2 # 2.5 지점에 2사분위수(중위수)가 위치해있다
p3 = ((len(ser)-1) / 4)*3 # 3.75 지점에 3사분위수가 위치해있다
# 선형 보간의 공식
# 1.25
Q1 = 4 + (9-4)*(0.25) # 5.25
# 2.5
Q2 = 9 + (15-9)*(0.5) # 12.0
# 3.75
Q3 = 15 + (16-15)*(0.75) # 15.75

IQR(Inter Quantile Range) 구하기
IQR = Q3 - Q1 # 10.5

정상치 구하기
max_limit = Q3 + IQR*1.5
min_limit = Q1 - IQR*1.5
max_limit, min_limit # (31.5, -10.5)

simplestatistics로 사분위 구하기
!pip install simplestatistics
import simplestatistics as ss
print(ss.quantile([0,4,9,15,16,17],[0.25,0.50,0.75])) # [4, 9, 16]

사분위수 구하는 여러가지 방법
i + (j-i)* fraction
ser.quantile(0.75, interpolation="linear") # 15.75
i
ser.quantile(0.75, interpolation="lower") # 15
j
ser.quantile(0.75, interpolation="higher") # 16
i or j whichever is nearest
ser.quantile(0.75, interpolation="nearest") # 16
(i+j)/2
ser.quantile(0.75, interpolation="midpoint") # 15.5

시각화 하기
#임의의 실수 100개를 가진 시리즈 생성
nums = np.random.random(100)
import matplotlib.pyplot as plt
plt.boxplot(nums)

예제
# 발견된 이상치를 현재 데이터의 평균값으로 대치해보세요
# 최대한계를 벗어난 데이터, 최소한계를 벗어난 데이터를 찾는다
# 각 이상치를 평균값으로 대치
import pandas as pd
import numpy as np

nums = np.random.random(100)
nums[0] = -2
nums[99] = 3

sr = pd.Series(nums)

describe = sr.describe()

Q1 = describe['25%']
Q2 = describe['50%']
Q3 = describe['75%']

IQR = Q3 - Q1

min_limit = Q1 - IQR*1.5
max_limit = Q3 + IQR*1.5

mean = sr.mean()

# outlier(이상치)
sr[sr<min_limit] = mean
sr[sr>max_limit] = mean

import matplotlib.pyplot as plot
plt.boxplot(sr)
plt.show()


데이터 분류
# 수치 -> 범주형
# 수치(1 ~ 100)
# 1 ~ 33 : 1, 34 ~ 66 : 2, 67 ~ 100 : 3

# 수치를 추정해야 하는 시스템 : 회귀(Regression)
# 범주를 추정해야 하는 시스템 : 분류(Classification)

예제
rg = np.arange(1,11)
ct = pd.cut(rg,3)
'''
[(0.991, 4.0], (0.991, 4.0], (0.991, 4.0], (0.991, 4.0], (4.0, 7.0], (4.0, 7.0], (4.0, 7.0], (7.0, 10.0], (7.0, 10.0], (7.0, 10.0]]
Categories (3, interval[float64, right]): [(0.991, 4.0] < (4.0, 7.0] < (7.0, 10.0]]
# (0.991, 4.0]
# 0.991를 포함하지 않고, 4.0을 포함한 범위
# (4.0, 7.0]
# 4.0를 포함하지 않고, 7.0을 포함한 범위
# (7.0, 10.0]
# 7.0를 포함하지 않고, 10.0을 포함한 범위
'''

Categories
ct.categories[0] # Interval(0.991, 4.0, closed='right'), closed는 포함이 되어있다는 뜻, 오른쪽이 포함된 범위

왼쪽과 오른쪽 값 추출
ct.categories[0].left, ct.categories[0].right # (0.991, 4.0)

왼쪽과 오른쪽의 포함 범위 알아내기
ct.categories[0].open_left, ct.categories[0].closed_right # (True, True)

# 위에서 나눈 범주 3개를 a, b, c 라고 이름을 붙인다면,
# 각 범주에 속하는 값들을 화면에 표시해보세요
list_ct = list(ct.categories)
'''
[Interval(0.991, 4.0, closed='right'),
 Interval(4.0, 7.0, closed='right'),
 Interval(7.0, 10.0, closed='right')]
'''
for i, ct in enumerate(list_ct):
    print(i,",")
    print(*list(item for item in rg if ct.left < item and item <= ct.right))
'''
0 ,
1 2 3 4
1 ,
5 6 7
2 ,
8 9 10
'''


이 블로그의 인기 게시물

Python 인공신경망 추천 시스템(회귀)

예제 # 인공신경망을 이용한 추천 시스템 # - 순차형(Sequential) 신경망 생성법 # - 함수형(Functional) 신경망 생성법 # - 지금까지 나온 추천 방식 중에서 가장 좋은 성능 # - Regression 방식으로 분석가능 # - 영화의 평점 정보(userid, movieid, rating) # - 이용자는 영화에 대한 취향이 모두 다르다 # - 영화는 다양한 장르가 혼합되어 있다 # - 이용자는 자신의 취향에 맞는 영화에 높은 rating을 제시함 # - 어떤 이용자에게 어떤 장르의 영화를 추천할 것인가? # __call__() 함수를 가진 클래스는 파이썬 함수 callable(클래스)를 사용하면 True를 반환한다 from tensorflow.keras.models import Sequential, Model from tensorflow.keras.layers import Dense, Embedding, Input input = Input(shape=(1,)) # 함수형 신경망 생성법 hidden1 = Dense(2, activation='relu')(input) # Dense(2, activation='relu')__call__() hidden2 = Dense(2, activation='relu')(hidden1) # callable.object callable(Dense) # __call__ 함수가 있으면 True, 없으면 False # Using Functional API from keras.models import Sequential from keras.layers import * model = Sequential() model.add(Input(shape=(3,))) # Input tensor model.add(Dense(4)) # hidden layer 1 model.add(Dense(units=4)) # hidden layer 2 model.add(Dense(units=1)) # ou...

Blogger

코드 하이라이트 사이트 http://hilite.me/ 코드 <!-- 나만의 공간 --> <style id='daru_css' type='text/css'> .code {      overflow: auto;      height: 200px;      background-color: rgb(239,239,239);      border-radius: 10px;      padding: 5px 10px; } .code::-webkit-scrollbar-thumb {      background-color: grey;      border: 1px solid transparent;      border-radius: 10px;      background-clip: padding-box;   } .code::-webkit-scrollbar {      width: 15px; } </style> <!-- 나만의 공간 -->

Python 문법

제곱 c = c**2; 주석 # 주석 함수 # 함수 형식 def hello(): # 함수 선언     print("여기는 함수") # 함수 실행문 hello() # 함수 호출 #결과: 여기는 함수 def add(a,b): # 매개변수에 자료형이 필요없다     c = a+b     print(f"{a} + {b} = {c}") add(3,5) #결과 : 3 + 5 = 8 if문 if a > b:     print("a가 큽니다") 객체의 정보 dir(객체) 객체의 주소 id(객체) 생략 if 'a' == 'a':     pass # 생략 else:     pass # 생략 enumerate for i,v in enumerate(range(20, 26)):     print(i,v) display display(df)