[python] 파이썬 Pandas Aggregate Function
파이썬 Pandas Aggregate Function에 대해서
Pandas DataReader
Pandas DataReader Package
웹 상의 데이터를 Pandas DataFrame 객체로 만드는 기능을 제공
Pandas DataReader Package 설치
- 터미널 실행
$ KANGs-MacBook-Pro ~ $ cd ~ ↳ cd ~ : 최상위 폴더로 이동
- 가상환경 접속
$ KANGs-MacBook-Pro ~ $ source activate data_env
- pandas_datareader 설치
$ (data_env) KANGs-MacBook-Pro:~ kang$ pip install pandas_datareader Collecting pandas_datareader Downloading https://files.pythonhosted.org/packages/cc/5c/ea5b6dcfd0f55c5fb1e37fb45335ec01cceca199b8a79339137f5ed269e0/pandas_datareader-0.7.0-py2.py3-none-any.whl (111kB) 100% |████████████████████████████████| 112kB 1.3MB/s Requirement already satisfied: pandas>=0.19.2 in /anaconda3/envs/data_env/lib/python3.6/site-packages (from pandas_datareader) (0.24.1) Collecting wrapt (from pandas_datareader) Downloading https://files.pythonhosted.org/packages/67/b2/0f71ca90b0ade7fad27e3d20327c996c6252a2ffe88f50a95bba7434eda9/wrapt-1.11.1.tar.gz Collecting requests>=2.3.0 (from pandas_datareader) Downloading https://files.pythonhosted.org/packages/7d/e3/20f3d364d6c8e5d2353c72a67778eb189176f08e873c9900e10c0287b84b/requests-2.21.0-py2.py3-none-any.whl (57kB) 100% |████████████████████████████████| 61kB 4.6MB/s Collecting lxml (from pandas_datareader) Downloading https://files.pythonhosted.org/packages/b5/5c/27b381a7d5b24ee4b9da1b02269a305bdc4fc30a3ea5bb21a5a98194850d/lxml-4.3.1-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (8.8MB) 100% |████████████████████████████████| 8.8MB 5.4MB/s Requirement already satisfied: python-dateutil>=2.5.0 in /anaconda3/envs/data_env/lib/python3.6/site-packages (from pandas>=0.19.2->pandas_datareader) (2.7.5) Requirement already satisfied: numpy>=1.12.0 in /anaconda3/envs/data_env/lib/python3.6/site-packages (from pandas>=0.19.2->pandas_datareader) (1.16.1) Requirement already satisfied: pytz>=2011k in /anaconda3/envs/data_env/lib/python3.6/site-packages (from pandas>=0.19.2->pandas_datareader) (2018.9) Collecting urllib3<1.25,>=1.21.1 (from requests>=2.3.0->pandas_datareader) Downloading https://files.pythonhosted.org/packages/62/00/ee1d7de624db8ba7090d1226aebefab96a2c71cd5cfa7629d6ad3f61b79e/urllib3-1.24.1-py2.py3-none-any.whl (118kB) 100% |████████████████████████████████| 122kB 3.1MB/s Requirement already satisfied: certifi>=2017.4.17 in /anaconda3/envs/data_env/lib/python3.6/site-packages (from requests>=2.3.0->pandas_datareader) (2018.11.29) Requirement already satisfied: idna<2.9,>=2.5 in /anaconda3/envs/data_env/lib/python3.6/site-packages (from requests>=2.3.0->pandas_datareader) (2.8) Collecting chardet<3.1.0,>=3.0.2 (from requests>=2.3.0->pandas_datareader) Downloading https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl (133kB) 100% |████████████████████████████████| 143kB 19.2MB/s Requirement already satisfied: six>=1.5 in /anaconda3/envs/data_env/lib/python3.6/site-packages (from python-dateutil>=2.5.0->pandas>=0.19.2->pandas_datareader) (1.12.0) Building wheels for collected packages: wrapt Building wheel for wrapt (setup.py) ... done Stored in directory: /Users/kang/Library/Caches/pip/wheels/89/67/41/63cbf0f6ac0a6156588b9587be4db5565f8c6d8ccef98202fc Successfully built wrapt Installing collected packages: wrapt, urllib3, chardet, requests, lxml, pandas-datareader Successfully installed chardet-3.0.4 lxml-4.3.1 pandas-datareader-0.7.0 requests-2.21.0 urllib3-1.24.1 wrapt-1.11.1
- 이제 jupyter notebook에서 pandas_datareader import 사용 가능.
Pandas Aggregate Function
pandas : python의 data analysis의 핵심 library
pandas는 고유하게 정의된 두개의 자료구조를 이용(시리즈, 데이터프레임)
DataFrame의 집계함수
- 변량 : 숫자들 ~ 평균 : 변량의 합 / 인원 수 편차 : 변량 - 평균 편차제곱 : 편차 * 편차 분산 : 편차의 제곱의 평균 표준편차 : 루트 분산
- 크다 : 평균을 기준으로 데이터가 흩어져있다라는 의미
- 작다 : 평균을 기준으로 데이터가 오밀조밀 모여있다는 의미
DataFrame의 생성과 사용에 기본적인 내용들.
- 평균(mean) : 여러개의 값이 있을 때, 그 값들에 대한 합을 개수로 나눈값, 수학적 확률의 기대치
- 편차(deviation) : 확률변수 X와 평균값에 대한 차이
- 분산(variance) : 편차의 제곱의 평균
- 표준편차(standard deviation) : 분산의 제곱근
import numpy as np arr = np.array([1,2,3,4,5], dtype=np.int64) print(arr.sum()) # 합계 # 결과값 : 15 print(arr.mean()) # 평균 # 결과값 : 3.0 print(arr.var()) # 분산 # 결과값 : 2.0 print(arr.std()) # 표준편차 # 결과값 : 1.4142135623730951
공분산(cov, covariance)
- 확률 변수가 2개일 때의 관계를 알아 볼때 공분산을 쓴다.
# 확률변수 X와 Y의 관계를 알기 위해서 사용하는 값 # X가 변할때 Y가 변하는 방향을 알기 위해서 사용 # X, Y가 서로 독립이면 공분산 0 # 공분산이 양수일경우 X가 증가하면 Y도 증가 # 공분산이 음수일경우 X가 증가하면 Y도 감소 # 양의 상관관계 ex) 삼성이 오르면 대체적으로 코스피도 오른다. # 음의 상관관계 ex) 남북경헙주 & 방산주 # 두 확률변수의 관계정도(strength)를 측정하기가 좋지 않다. => 상관계수 # 양수든 음수든 상관없이 두개의 밀접한 관계를 알 수 있는 건 => 상관계수
공분산이 양수인 경우
- 예) KOSPI지수와 삼성전자 주가
# 사이트에서 바로 분석하는 방법 import numpy as np import pandas as pd import datetime import pandas_datareader.data as pdr start = datetime.datetime(2018,1,1) end = datetime.datetime(2018,12,31) # Yahoo에서 제공하는 코스피 지수정보를 가져와서 DataFrame df_KOSPI = pdr.DataReader("^KS11","yahoo",start,end) #사이트에서 정보 가져오기 df_KOSPI.to_json("./data/stock/KOSPI.json") # 정보를 파일로 저장 df_KOSPI.head(5)
공분산이 양수인 경우
- 예) KOSPI지수와 삼성전자 주가
- 위의 방법으로 접속 불가능시 아래와 같이 실행
- 파일로 분석하는 방법
import numpy as np import pandas as pd import datetime import pandas_datareader.data as pdr start = datetime.datetime(2018,1,1) end = datetime.datetime(2018,12,31) #코스피 주식 가져오기 #df_KOSPI = pd.read_json("./data/stock/KOSPI.json") #JSON 파일 정보 전체 가져오기 df_KOSPI = pd.read_json("./data/stock/KOSPI.json")["Close"] #"Close" column만 가져오기(Series형태이다.) #print(df_KOSPI.head(5)) #삼성전자 주식 가져오기 #df_SE = pd.read_json("./data/stock/SE.json") #JSON 파일 정보 전체 가져오기 df_SE = pd.read_json("./data/stock/SE.json")["Close"] #"Close" column만 가져오기(Series형태이다.) #print(df_SE.head(5)) # KOSPI와 SE이 두개의 확률변수를 가지고 공분산(covariance)을 구해보자. np.cov(df_KOSPI, df_SE) # 결과값 # array([[ 24177.23140621, 490222.10530186], # [ 490222.10530186, 11919911.50745464]]) # (0,0) KOSPI KOSPI # (0,1) KOSPI & SE # (1,0) SE & KOSPI # (1,1) SE & SE # 값의 의미는 모르겠으나 양수이기 때문에 양의 공분산이라는걸 알 수 있다.
공분산이 음수인 경우¶
- 예) 남북경협주와 방산주
# 파일로 분석하는 방법 import numpy as np import pandas as pd import datetime import pandas_datareader.data as pdr start = datetime.datetime(2018,1,1) end = datetime.datetime(2018,12,31) #부산산업 주식 가져오기 #df_BUSAN = pd.read_json("./data/stock/부산산업.json") #JSON 파일 정보 전체 가져오기 df_BUSAN = pd.read_json("./data/stock/부산산업.json")["Close"] #"Close" column만 가져오기(Series형태이다.) #print(df_BUSAN.head(5)) #LIG넥스원 주식 가져오기 #df_LIG = pd.read_json("./data/stock/LIG넥스원.json") #JSON 파일 정보 전체 가져오기 df_LIG = pd.read_json("./data/stock/LIG넥스원.json")["Close"] #"Close" column만 가져오기(Series형태이다.) #print(df_LIG.head(5)) # 부산산업과 LIG넥스원 두개의 확률변수를 가지고 공분산(covariance)을 구해보자. np.cov(df_BUSAN, df_LIG) # 결과값 # array([[ 4.64762211e+09, -3.86535936e+08], # [-3.86535936e+08, 6.35924170e+07]]) # (0,0) BUSAN BUSAN # (0,1) BUSAN LIG # (1,0) LIG BUSAN # (1,1) LIG LIG # 값의 의미는 모르겠으나 양수이기 때문에 양의 공분산이라는걸 알 수 있다.
상관관계(corelation), 상관계수(corelation coefficient)
- 상관관계(corelation)
- 서로 연관이 있어보이는 관계 ex) 성적과 자존감, 온라인게임과 폭력성
- 상관계수(corelation coefficient)
- 값이 항상 -1 ~ +1 사이의 실수로 표현한다.
- 0에 가까울 수록 서로 연관성이 없는 관계를 나타낸다.
- 절대값이 1에 가까울수록 연관성이 높다.
- 상관계수는 두개의 확률변수에 대한 연관성에 대한 지표이지 인과관계(원인과 결과)를 설명하지 않는다.
- 그래서 오류의 소지가 다분하다.
상관계수 구해보기(1)
import numpy as np
import pandas as pd
import datetime
import pandas_datareader.data as pdr
start = datetime.datetime(2018,1,1)
end = datetime.datetime(2018,12,31)
df_KOSPI = pd.read_json("./data/stock/KOSPI.json")["Close"]
df_SE = pd.read_json("./data/stock/SE.json")["Close"]
np.corrcoef(df_KOSPI, df_SE)
# 결과값
# array([[1. , 0.91317306],
# [0.91317306, 1. ]])
# (0,0) df_KOSPI df_KOSPI
# (0,1) df_KOSPI df_SE
# (1,0) df_SE df_KOSPI
# (1,1) df_SE df_SE
# 0~0.3 약한관계, 0.3~0.7 중간관계, 0.7~1 강한관계를 뜻한다.
상관계수 구해보기(2)
import numpy as np
import pandas as pd
import datetime
import pandas_datareader.data as pdr
start = datetime.datetime(2018,1,1)
end = datetime.datetime(2018,12,31)
df_BUSAN = pd.read_json("./data/stock/부산산업.json")["Close"]
df_LIG = pd.read_json("./data/stock/LIG넥스원.json")["Close"]
np.corrcoef(df_BUSAN, df_LIG)
# 결과값
# array([[ 1. , -0.71100361],
# [-0.71100361, 1. ]])
# 0~0.3 약한관계, 0.3~0.7 중간관계, 0.7~1 강한관계를 뜻한다.
pandas 통계적 함수 사용
# numpy를 이용해서 통계적인 내용을 해왔다.
# 이번엔 pandas(DataFrame)를 이용한 통계적인 함수 사용법을 알아보자.
import numpy as np
import pandas as pd
data = [[2, np.nan], # 4행 2열의 리스트
[7, -3],
[np.nan, np.nan],
[1, -2]]
df = pd.DataFrame(data,
columns=["one","two"],
index=["a","b","c","d"])
display(df)
display(df.sum()) # axis가 생략, axis=0 default
display(df.mean()) # default로 NaN은 배제하고 계산
display(df.sum(axis=1)) # 축을 기준으로 Series형태로 계산된다.
간단한 문제
- 결측값이 있으면 계산이 불확실해진다.
- 그래서 결륵값을 해결해야 한다. (삭제 또는 다른값으로 대체해야한다.)
- one column의 결측값은 one column의 평균으로 대체
- two column의 결측값은 two column의 최소값으로 대체
- 결측값을 대체하고 DataFrame을 출력
import numpy as np import pandas as pd data = [[2, np.nan], # 4행 2열의 리스트 [7, -3], [np.nan, np.nan], [1, -2]] df = pd.DataFrame(data, columns=["one","two"], index=["a","b","c","d"]) print("▼ 기본") display(df) one_value = df["one"].mean() # one column의 평균 two_value = df["two"].min() # two column의 최소값 df["one"] = df["one"].fillna(value=one_value) df["two"] = df["two"].fillna(value=two_value) print("▼ 결과값") display(df) # 결측값을 대체하고 DataFrame을 출력
DataFrame에서 공분산과 상관계수 구하기 +@ JSON 파일 기준으로
import numpy as np
import pandas as pd
df_BUSAN = pd.read_json("./data/stock/부산산업.json")["Close"]
df_LIG = pd.read_json("./data/stock/LIG넥스원.json")["Close"]
df_KOSPI = pd.read_json("./data/stock/KOSPI.json")["Close"]
df_SE = pd.read_json("./data/stock/SE.json")["Close"]
data = {"KOSPI" : df_KOSPI,
"SE" : df_SE,
"LIG" : df_LIG,
"BUSAN" : df_BUSAN}
df = pd.DataFrame(data)
df["BUSAN"].cov(df["KOSPI"]) #공분산 구하기 -6113069.91603586
df["BUSAN"].corr(df["KOSPI"]) #상관계수 구하기 -0.5766876815236214
display(df.cov()) # DataFrame 공분산 구하기
display(df.corr()) # DataFrame 상관계수 구하기
DataFrame이 제공하는 유용한 함수
- 정렬(1) index를 통해서 정렬
import numpy as np import pandas as pd np.random.seed(0) df = pd.DataFrame(np.random.randint(0,10,(6,4)), columns=["A","B","C","D"], index=pd.date_range("20190101",periods=6)) random_index = np.random.permutation(df.index) # np가 제공하는 랜덤을 순열(연속적인 값의 집합) df2 = df.reindex(index=random_index, columns=["B","D","C","A"]) # display(df2) # sort_index() 인덱스를 이용해서 재정렬 할 수 있다. display(df2.sort_index(axis=0, ascending=False)) #axis=0(행 방향으로 정렬) #False(내림차순) display(df2.sort_index(axis=1, ascending=False)) #axis=1(열 방향으로 정렬) #False(내림차순) #default값은 오름차순 그래서 False하면 내림차순이 된다.
DataFrame이 제공하는 유용한 함수
- 정렬(2) data값을 통해서 정렬
import numpy as np import pandas as pd np.random.seed(0) df = pd.DataFrame(np.random.randint(0,10,(6,4)), columns=["A","B","C","D"], index=pd.date_range("20190101",periods=6)) random_index = np.random.permutation(pd.date_range("20190101",periods=6)) #리스트 안에 있는 요소들을 섞어주는 역할 df.index = random_index df.columns = ["B","A","C","D"] display(df) display(df.sort_values(by="B", ascending=False)) #default 값은 오름차순 그래서 False는 내림차순 display(df.sort_values(by=["B","A"])) #B를 갖고 정렬한다음 값이 같으면 A를 기준으로 정렬해
DataFrame이 제공하는 유용한 함수
- unique()
- value_counts()
- isin()
- lambda 입력값 : 해야할 일
import numpy as np import pandas as pd np.random.seed(0) df = pd.DataFrame(np.random.randint(0,10,(6,4)), columns=["A","B","C","D"], index=pd.date_range("20190101",periods=6)) df["E"] = ["AA","BB","CC","AA","CC","CC"] # 새로운 column 추가 display(df) # unique() print(df["E"].unique()) #어떤 종류?값이 있니? # value_counts() print(df["E"].value_counts()) #값의 개수를 카운팅 # isin() print(df["E"].isin(["AA","BB"])) # 어디어디에 포함되어 있니? True/False 값으로 나와서 # boolean indexing 처리가능 df.drop("E",axis=1,inplace=True) # drop으로 삭제할때 어떤걸 삭제할지랑 axis축 값을 정해야한다. # inplace=True 원본을 변경해라는 의미 display("isin",df) # lambda : 한줄짜리 함수를 만들 때 쓴다. # 최대값에서 최소값을 뺀후 E라는 새로운 column에 추가하는 방법 func = lambda x : x.max() - x.min() #x: 입력값 : 해야할 일 등을 처리 후 return 하겠어라는 의미 df.apply(func,axis=1) # 이 함수를 저장해 라는 의미(적용할 함수명, 축값(axis=0 행, axis=1 열)) display(df.apply(func,axis=1)) df["Max-Min"] = df.apply(func,axis=1) display(df)
DataFrame이 제공하는 유용한 함수 merge(1)
- merge : (1) key값이 같은 경우의 merge
#(1) key값이 같은 경우의 merge # Pandas(merge) = SQL(Inner join, Outer join, Left Outer join, Right Outer join) # merge() 함수를 이용해서 join 작업을 수행(DataFrame의 결합) import numpy as np import pandas as pd df1 = pd.DataFrame({"학번" : ["2019001","2019002","2019003"], "이름" : ["이지안","박동훈","홍길동"]}) df2 = pd.DataFrame({"학번" : ["2019001","2019003","2019004"], "학과" : ["컴퓨터","철학","수학"]}) print("▼ inner join") display(pd.merge(df1, df2, on="학번", how="inner")) # 학번을 기준으로 merge print("▼ outer join") display(pd.merge(df1, df2, on="학번", how="outer")) print("▼ left join") display(pd.merge(df1, df2, on="학번", how="left")) print("▼ right join") display(pd.merge(df1, df2, on="학번", how="right"))
DataFrame이 제공하는 유용한 함수 merge(2)
- merge : (2) key값이 다른 경우의 merge
import numpy as np import pandas as pd df1 = pd.DataFrame({"학번" : ["2019001","2019002","2019003"], "이름" : ["이지안","박동훈","홍길동"]}) df2 = pd.DataFrame({"학생학번" : ["2019001","2019003","2019004"], "학과" : ["컴퓨터","철학","수학"]}) # df1과 df2의 키값이 다른 경우 사용법 pd.merge(df1, df2, left_on="학번", right_on="학생학번", how="inner")
DataFrame이 제공하는 유용한 함수 merge(3)
- merge : (3) column기반과 index기반의 merge
import numpy as np import pandas as pd df1 = pd.DataFrame({"학번" : ["2019001","2019002","2019003"], "이름" : ["이지안","박동훈","홍길동"]}) df2 = pd.DataFrame({"학과" : ["컴퓨터","철학","수학"]}, index=["2019001","2019003","2019004"]) display(df1) #학번이 column으로 잡히고 display(df2) #학번이 index로 잡힘 display(pd.merge(df1, df2, left_on="학번", right_index=True, how="inner"))
References
개발자님들 덕분에 많이 배울 수 있었습니다. 감사의 말씀 드립니다.