판다스는 내부적으로 2개의 자료구조를 가진다.
Numpy는 ndarry를 판다스는 2개를 가진다.
series : 1차원 자료구조, 같은 data type만 저장 가능
DataFrame : 2차원 자료구조 series의 집합
시리즈의 집합이 데이터 프레임이다!
Pandas는 외부 module이기 때문에 설치를해서 사용해야 한다
conda install pandas
- 예제를 통해 알아보자
import numpy as np import pandas as pd # ndarray를 생성해보자 arr = np.array([1,2,3,4,5], dtype = np.float64) print(arr) # [1. 2. 3. 4. 5.] # series를 설정해 보자 s = pd.Series([1,2,3,4,5], dtype=np.float64) print(s) print(s.values) # [1. 2. 3. 4. 5.] ndarray로 print(s.index) # RangeIndex(start=0, stop=5, step=1) => pands의 객체 print(s.dtype) # float64 # 시리즈는 1차원 ndarray에 값을 가져와 인덱스와 함께 출력해줌
- Pandas Series의 인덱스를 따로 잡는 방법
# 인덱스를 따로 잡는 방법 import numpy as np import pandas as pd s = pd.Series([1, 2, 3, 4, 5], dtype=np.float64, index = ['c', 'b', 'a', 'kk', '홍길동' ]) # print(s) # c 1.0 # b 2.0 # a 3.0 # kk 4.0 # 홍길동 5.0 # dtype: float64 # 만약 인덱스를 지정해서 Series를 만들면 숫자 index는 어떻게 되나? # 숫자 index는 그대로 사용가능, 내부에 숨어있어요! print(s[0]) # 숫자 index를 활용하여 1.0 출력 print(s['c']) # 지정 indx 1.0 # # print(s[100]) # Error 100번째 칸이 없어요!
- 지정 index를 숫자로 사용하면 어떻게 되나
import numpy as np import pandas as pd s = pd.Series([1, 2, 3, 4, 5], dtype=np.float64, index = [0, 2, 100, 6, 9]) print(s) # 0 1.0 # 2 2.0 # 100 3.0 # 6 4.0 # 9 5.0 print(s[0]) # 1.0 # print(s[1]) # Error print(s[100]) # 3.0 # 지정 index가 숫자로 되어있으면 기존에 있던 숫자 인덱스는 사용 못한다1
- 지정 index에 같은 index가 전해면 어떻게 되나요? 가능!!!!!
import numpy as np import pandas as pd s = pd.Series([1, 2, 3, 4, 5], dtype=np.float64, index = ['c', 'b', 'c', 'k', 'm']) print(s) # c 1.0 # b 2.0 # c 3.0 # k 4.0 # m 5.0 print(s['c']) # 같은인덱스로 되어있는것을 indexing하면 여러개를 가져옴 결국 시리즈형태로 값이 떨어짐 # c 1.0 # c 3.0 # dtype: float64
- Pandas의 indexing, slicing
# indexing, slicing # indexin은 ndarray나 list와 비슷! # 단, slicing은 약간 주의해야해요! import numpy as np import pandas as pd s = pd.Series([1, 2, 3, 4, 5], dtype=np.float64, index = ['c', 'b', 'a', 'k', 'm']) print(s) # c 1.0 # b 2.0 # a 3.0 # k 4.0 # m 5.0 # dtype: float64 print(s[0:3]) # 숫자 index를 이용한 slicing(ndarray와 list와 동일) # c 1.0 # b 2.0 # a 3.0 # dtype: float64 print(s['c':'a']) # 지정 index를 사용할때는 앞에도 포함 뒤에도 포함이기 때문에 포함할 위치를 slicing해줘야함 # c 1.0 # b 2.0 # a 3.0 # dtype: float64
- Pandas의 boolean indexing fancy indexing
# boolean indexing, fancy indexing 역시 적용이 가능 import numpy as np import pandas as pd s = pd.Series([1, 2, 3, 4, 5], dtype=np.float64, index = ['c', 'b', 'a', 'k', 'm']) print(s) # c 1.0 # b 2.0 # a 3.0 # k 4.0 # m 5.0 # dtype: float64 # 짝수만 뽑아내는 boolean indexing print(s[s%2==0]) # b 2.0 # k 4.0 # dtype: float64 # fancy indexing print(s[[0,2]]) # c 1.0 # a 3.0 # dtype: float64
Series를 만드는 또다른 방법에 대해서도 알아보자!
# index를 key로 저장하는 값을 value로 구성되는 자료구조 # s = pd.Series([1, 2, 3, 4, 5], # dtype=np.float64, # index = ['c', 'b', 'a', 'k', 'm']) # dictionary를 이용해서 Series를 생성 my_dict = {'서울': 1000, '인천': 500, '제주': 200} s = pd.Series(my_dict) print(s)
결과 서울 1000 인천 500 제주 200 dtype: int64
- 문제 1
### A공장의 2020년 1월 1일부터 10일간 생산량의 Series로 저장 # 생산량의 평균이 50이고 표준편차가 5인 정규분포에서 랜덤하게 생성(정수) ### B공장의 2020년 1월 1일부터 10일간 생산량의 Series로 저장 # 생산량의 평균이 70이고 표준편차가 8인 정규분포에서 랜덤하게 생성(정수) # index가 날짜 import numpy as np import pandas as pd from datetime import datetime, timedelta # 날짜에 대한 간격을 표현 timedelta start_day = datetime(2020,1,1) print(start_day) # 2020-01-01 00:00:00 # list comprehension => list 생성시 제어문을(for, if) 이용하여 값을 넣어줌 s1 = pd.Series([int(x) for x in np.random.normal(50,5,(10,))], index=[start_day + timedelta(days=x) for x in range(10)]) print(s1) 2020-01-01 00:00:00 2020-01-01 52 2020-01-02 53 2020-01-03 52 2020-01-04 59 2020-01-05 51 2020-01-06 45 2020-01-07 52 2020-01-08 41 2020-01-09 54 2020-01-10 46 dtype: int64 s2 = pd.Series([int(x) for x in np.random.normal(70,8,(10,))], index=[start_day + timedelta(days=x) for x in range(10)]) print(s2) 2020-01-01 72 2020-01-02 71 2020-01-03 76 2020-01-04 68 2020-01-05 71 2020-01-06 71 2020-01-07 65 2020-01-08 68 2020-01-09 66 2020-01-10 64 dtype: int64 # 날짜별로 생산량의 합을 구하세요! print(s1+s2) 2020-01-01 124 2020-01-02 124 2020-01-03 128 2020-01-04 127 2020-01-05 122 2020-01-06 116 2020-01-07 117 2020-01-08 109 2020-01-09 120 2020-01-10 110 dtype: int64
- 문제 2
# 날짜를 다르게해서 생산량의 합을 구해보아요! ### A공장의 2020년 1월 1일부터 10일간 생산량의 Series로 저장 # 생산량의 평균이 50이고 표준편차가 5인 정규분포에서 랜덤하게 생성(정수) ### B공장의 2020년 1월 5일부터 10일간 생산량의 Series로 저장 # 생산량의 평균이 70이고 표준편차가 8인 정규분포에서 랜덤하게 생성(정수) # index가 날짜 import numpy as np import pandas as pd from datetime import datetime, timedelta # 날짜에 대한 간격을 표현 timedelta start_day_A_factory = datetime(2020,1,1) start_day_B_factory = datetime(2020,1,5) # list comprehension => list 생성시 제어문을(for, if) 이용하여 값을 넣어줌 s1 = pd.Series([int(x) for x in np.random.normal(50,5,(10,))], index=[start_day_A_factory + timedelta(days=x) for x in range(10)]) print(s1) 2020-01-01 48 2020-01-02 57 2020-01-03 42 2020-01-04 49 2020-01-05 44 2020-01-06 42 2020-01-07 55 2020-01-08 42 2020-01-09 47 2020-01-10 60 dtype: int64 s2 = pd.Series([int(x) for x in np.random.normal(70,8,(10,))], index=[start_day_B_factory + timedelta(days=x) for x in range(10)]) print(s2) 2020-01-05 85 2020-01-06 74 2020-01-07 79 2020-01-08 64 2020-01-09 65 2020-01-10 73 2020-01-11 58 2020-01-12 76 2020-01-13 57 2020-01-14 56 dtype: int64 # 날짜별로 생산량의 합을 구하세요! print(s1+s2) 2020-01-01 NaN 2020-01-02 NaN 2020-01-03 NaN 2020-01-04 NaN 2020-01-05 129.0 2020-01-06 116.0 2020-01-07 134.0 2020-01-08 106.0 2020-01-09 112.0 2020-01-10 133.0 2020-01-11 NaN 2020-01-12 NaN 2020-01-13 NaN 2020-01-14 NaN dtype: float64 # 데이터가 일치하지 않는 갑은 NaN으로 출력이 되는 것을 확인 할 수 있다!
DataFrame : 2차원 atrix 구소
DataFrame은 시리즈의 집합이라 보면된다.
즉, 시리즈를 하나로 세워서 합쳐놓은 2차원 매트릭스 구조!
각각의 컬럼별로는 동일한 데이터를 가지지만 전체적으로는 서로 다른 데이터 타입을 가지고 있을 수 있다!
컬럼 컬럼 index 데이터 데이터
- 데이터 프레임은 다음과 같은 형식으로 구성 된다.
코드로 표현해보자!
# DataFrame은 dictionary를 이용해서 만들어요! import numpy as np import pandas as pd my_dict = {'이름':['홍길동', '아이유', '김연아', '신사임당'], '학년':[4, 3, 2, 1], '학점':[1.5, 2.4, 3.9, 3.2]} # key 값이 컬럼명 데이터 값이 각각의 시리즈로 탁 들어가게 됨 # index는 따로 잡지 않아 숫자 인덱스가 할당이 되는것을 볼 수 있음 df = pd.DataFrame(my_dict) display(df) # 이름 학년 학점 # 0 홍길동 4 1.5 # 1 아이유 3 2.4 # 2 김연아 2 3.9 # 3 신사임당 1 3.2 # DataFrame의 기본 속성 print(df.shape) # (4, 3) # 내부 값들은 2차원 ndarray이기 때문에 값만 뽑아라! 라는 명령을 실행하면 다음과 같이 나온다. print(df.values) # [['홍길동' 4 1.5] # ['아이유' 3 2.4] # ['김연아' 2 3.9] # ['신사임당' 1 3.2]] print(df.size) # DataFrame안의 요소 개수 12 print(df.ndim) # 몇차원인가? 2 print(df.index) # 행 index RangeIndex(start=0, stop=4, step=1) print(df.columns) # 열 index index(['이름', '학년', '학점'], dtype='object') df.index.name = '학번' df.columns.name = '학생정보' display(df) #학생정보 이름 학년 학점 #학번 # 0 홍길동 4 1.5 # 1 아이유 3 2.4 # 2 김연아 2 3.9 # 3 신사임당 1 3.2
- DataFrame의 column명과 index명 변경하기!
import numpy as np import pandas as pd my_dict = {'이름':['홍길동', '아이유', '김연아', '신사임당'], '학년':[4, 3, 2, 1], '학점':[1.5, 2.4, 3.9, 3.2]} df = pd.DataFrame(my_dict) display(df) # 이름 학년 학점 # 0 홍길동 4 1.5 # 1 아이유 3 2.4 # 2 김연아 2 3.9 # 3 신사임당 1 3.2 # 데이터 프레임의 이름을 바꿔준다. 1. 컬러명 2. index 명 new_df = df.rename(columns={'이름':'학생이름', '학점':'평균평점'}, index={0:'one'}, inplace=False) # inplace는 복사본을 만들건지 원본을 수정할건지를 의미 # 옵션값 True면 원본 수정하고 복사본 생성 x # 옵션값 False면 원본은 냅두고 복사본 생성 o # 이렇게 rename을 사용하면 컬러명 index명을 변경 할 수 있다! display(new_df) # 학생이름 학년 평균평점 # one 홍길동 4 1.5 # 1 아이유 3 2.4 # 2 김연아 2 3.9 # 3 신사임당 1 3.2
- DataFrame의 특정 column을 index로 설정하는 방법
# 예를들어서 이름 column을 index로 설정해보아요 # set_index()를 사용하면 된다. import numpy as np import pandas as pd my_dict = {'이름':['홍길동', '아이유', '김연아', '신사임당'], '학년':[4, 3, 2, 1], '학점':[1.5, 2.4, 3.9, 3.2]} df = pd.DataFrame(my_dict) display(df) # 이름 학년 학점 # 0 홍길동 4 1.5 # 1 아이유 3 2.4 # 2 김연아 2 3.9 # 3 신사임당 1 3.2 new_df = df.set_index('이름', inplace=False) display(new_df) # 학년 학점 # 이름 # 홍길동 4 1.5 # 아이유 3 2.4 # 김연아 2 3.9 # 신사임당 1 3.2
여기 까지가 Data Frame의 기본 사항이다
이제는 여러가지 resource를 이용해서 DataFrame을 생성해보도록 하자!
ex) csv, MySQL, Database, Open APL 등
예시를 한번 보겠다.
import numpy as np import pandas as pd df = pd.read_csv('./data/student.csv') display(df) 이름 입학연도 성적 0 아이유 2015 1.5 1 김연아 2016 2.0 2 홍길동 2015 3.1 3 강감찬 2017 1.1 4 이순신 2016 2.7
- 이런식으로 csv 파일을 불러와 pandas가 가지고 있는 read_csv를 이용하여 해당 파일을 불러 올 수 있다.