이 게시글은 데이터사이언스엔지니어링_전문가 과정을 수강하며 복습을 위해 정리한 글입니다.
판다스 설명(pandas)
- series, DataFrame등의 자료구조를 활용한 데이터분석 기능을 제공해주는 라이브러리
- 라이브러리 구성
- 여러종류의 클래스와 다양한 함수로 구성
- 시리즈와 데이터 프레임의 자료 구조 제공
- 시리즈(1차원 배열) 데이터프레임(2차원 행열구조)
판다스의 목적
- 서로 다른 유형의 데이터를 공통된 포맷으로 정리하는 것
- 행과 열로 이루어진 2차원 데이터프레임을 처리 할 수 있는 함수제공 목적
- 실무 사용 형태 : 데이터 프레임
Series
- pandas의 기본 객체 중 하나
- numpy의 ndarray를 기반으로 인덱싱을 기능을 추가하여 1차원 배열을 나타냄
- index를 지정하지 않을 시, 기본적으로 ndarray와 같이 0-based 인덱스 생성, 지정할 경우 명시적으로 지정된 index를 사용
- 같은 타입의 0개 이상의 데이터를 가질 수 있음
- 자료구조: 시리즈
- 데이터가 순차적으로 나열된 1차원 배열 형태
- 인덱스(index)와 데이터 값(value)이 일대일로 대응
- 딕셔너리와 비슷한 구조 : {key(index):value}
- 시리즈의 인덱스
- 데이터 값의 위치를 나타내는 이름표 역할
- 시리즈 생성 : 판다스 내장함수인 Series()이용
- 리스트로 시리즈 만들기
- 딕셔너리로 시리즈 만들기
- 튜플로 시리즈 만들기
판다스 모듈 import
- 대부분의 코드에서 pandas 모듈은 pd 라는 별칭을 사용함
- 데이터분석에서 pandas와 numpy 두 패키지는 기본 패키지로 본다
- numpy는 np라는 별칭을 사용
import pandas as pd
import numpy as np
Series 생성하기
- data로만 생성하기
- index는 기본적으로 0부터 자동적으로 생성
# pd.Series : 집합적 자료형, 리스트
s = pd.Series([1,2,3])
s
** Series data로 정수,실수,문자열 다 가능하다. 하지만 반드시 집합적 자료형을 이용해 하나의 인수로 만들어 사용해야한다.
pd.Series(1,2,3)
# TypeError: Index(...) must be called with a collection of some kind, 2 was passed
** Series 리스트내에 서로 다른 type의 데이터가 있으면 형변환이 일어난다.
s = pd.Series(['a',1,3.0]) # 문자열로 형변환되어 저장
s
- 범위를 시리즈의 value 생성하는 데 사용하기 - range/np.arange 함수 사용
# 10~13 범위의 수로 0_base의 시리즈 생성
s1 = pd.Series(range(10,14))
s1
# numpy에서 지원하는 arange함수를 이용하여
# 0~199 범위의 0_base의 시리즈 생성
# 위의 코드와 다른 점은 Length : 200 속성값을 포함한다.
s2 = pd.Series(np.arange(200))
s2
- 결측값을 포함해서 시리즈 만들기
- 결측값 NaN - numpy 라는 모듈에서 생성할 수 있음
- 결측값 생성 위해서는 numpy 모듈 import
# NaN은 np.nan 속성을 이용해서 생성
s = pd.Series([1,2,3,np.nan,6,8])
s
# dtype: float64
# 판다스가 처리하는 자료구조인 시리즈와
# 데이터프레임에서 결측치가 있는 경우는 datatype이 float으로 변경(수치)
- 인덱스 명시해서 시리즈 만들기
- 숫자 인덱스 지정
- s = pd.Series([값1,값2,값3],index=[1,2,3])
s = pd.Series([10,20,30],index=[1,2,3])
s
# index를 명시해주지 않고 Series를 생성할 경우 0_base로 0부터 인덱스가 자동 지정된다.
# 하지만 index= 를 통해 인덱스를 명시하면 원하는 값으로 지정할 수 있다.
- 문자 인덱스 지정
s = pd.Series([95,100,88],index=['홍길동','이몽룡','성춘향'])
s
- 인덱스 활용 : 시리즈의 index
- 시리즈의 index는 index 속성으로 접근
# 인덱스를 명시한 경우
s = pd.Series([10,20,30],index=[1,2,3])
s.index
# index를 명시하지 않은 경우
s = pd.Series([1,2,3])
s.index # 범위 인덱스가 생성
s= pd.Series([9904312,3448737,289045,2466052],
index=["서울","부산","인천","대구"])
s.index
- 시리즈.index.name 속성
- 시리즈의 인덱스에 이름을 붙일 수 있음
s.index.name = '광역시'
s
- 시리즈의 값: numpy 자료구조 - 1차원 배열
- values 속성으로 접근
- 시리즈.values
s.values
# 시리즈의 값의 전체 형태는 array(numpy의 자료구조) 형태
- 시리즈.name 속성
- 시리즈 데이터에 이름을 붙일 수 있다.
- name 속성은 값의 의미 전달에 사용
s.name = '인구'
s
시리즈의 인덱싱 종류
- 정수형 위치 인덱스(integer position)
- 인덱스 이름(index name) 또는 인덱스 라벨(index label)
- 인덱스 별도 지정하지 않으면 0부터 시작하는 정수형 인덱스가 지정됨
- 정수형 인덱스 : 숫자 s[0]
- 문자형 인덱스 : 문자 s['인천']
# 문자형 인덱스의 경우
s['인천'] # 문자형 인덱스로 접근
s[2] # 위치 인덱스 사용 가능
# 정수형 인덱스인 경우
s03=pd.Series([1,2,3], index=[1,2,3])
s03[1] # 명시적 인덱스(정수인덱스) 사용
# s03[0] # 위치 인덱스 접근 - KeyError: 0
# 정수인덱스인 경우 위치인덱스는 사용 불가
# 문자형 인덱스(부산 데이터 추출)
s['부산']
# 3448737
# 두개 이상의 인덱싱 코드를 나열하면 - 튜플형태로 반환
s[3],s['대구']
# (2466052, 2466052)
리스트 이용 인덱싱
- 자료의 순서를 바꾸거나 특정자료 여러개를 선택할 수 있다.
- 인덱스값 여러개를 이용해 접근시 []안에 넣는다
# s[0,3,1] # KeyError: (0, 3, 1) 'key of the tuple not found and not a MultiIndex'
s[0],s[3],s[1] # (9904312, 2466052, 3448737)
# 시리즈명[[인덱스리스트]] - 시리즈 형태로 반환
s[[0,3,1]] # - 인덱스 리스트 내의 해당 item을 추출 후 시리즈 형태로 반환
시리즈 슬라이싱
- 정수형 위치 인덱스를 사용한 슬라이싱
- 시리즈[start:stop+1]
- 문자(라벨)인덱스 이용 슬라이싱
- 시리즈['시작라벨':'끝라벨'] : 표시된 라벨 범위 모두 추출
# 문자형 인덱스를 명시했을 경우
# 문자인덱스를 이용한 슬라이싱 가능
# 표시된 문자인덱스 범위 모두 추출
s['부산':'대구']
# 위치인덱스 슬라이싱 가능 1~2
s[1:3]
####################################
# 정수형 인덱스를 명시했을 경우
s_01 = pd.Series([100,200,300,400], index=[1,2,3,4])
s_01[2:4]
# '부산':'대구' 했듯이 명시된 index 슬라이싱으로 접근하길 원했지만
# 0_base 위치 인덱스 슬라이싱을 사용
# 시리즈의 인덱스를 명시할때는 가급적으면 문자형으로 명시하는 것이 좋다
문자 인덱스
- [.]연산자를 이용하여 접근가능
# 인덱스를 문자값으로 지정한 시리즈
s0 = pd.Series(range(3),index=['a','b','c'])
s0
s0['a']
s0.a
# 동일하게 0 값이 반환된다.
s['서울']
s.서울 # 한글문자 인덱스도 가능하다.
인덱스 통한 데이터 업데이트
# 인덱스로 접근하여 데이터 저장 - 원본반영
s['서울'] = 100000000
인덱스 재사용 하기
# s시리즈의 index값을 그대로 가져와 명시해줄 수 있다.
s1 = pd.Series(np.arange(4),s.index)
시리즈 연산
벡터화 연산
- numpy 배열처럼 pandas의 시리즈도 벡터화 연산 가능
- 벡터화 연산이란 집합적 자료형의 원소 각각을 독립적으로 계산을 진행하는 방법
- 단, 연산은 시리즈의 값에만 적용되며 인덱스 값은 변경 불가
# 시리즈 원소 각각에 대하여 +4 연산을 진행 - 벡터화 연산
pd.Series([1,2,3]) + 4
# s 시리즈의 단위가 커서 단위를 변경하고자 함 1/1000000
# 시리즈 자체를 100000으로 나누면 됨, 벡터화연산을 진행 함
s/1000000
# 벡터화 인덱싱도 가능
# 시리즈[조건]
# s시리즈 값 중 2500000 보다 크고 5000000 보다 작은 원소 추출
s[(s>250e4) & (s<500e4)]
# s 시리즈 각 원소값 각각에 대해서 조건식을 확인해서 결과가 True인 원소를 반환
Boolean selection
- boolean Series가 []와 함께 사용되면 True 값에 해당하는 값만 새로 반환되는 Series객체에 포함됨
- 다중조건의 경우, &(and), |(or)를 사용하여 연결 가능
s0 = pd.Series(np.arange(10), np.arange(10)+1)
s0
s0 > 5
# Boolean selection으로 True가 나온 값만 시리즈로 반환
s0[s0>5]
(s0 >= 7).sum() # True의 개수 총 합
(s0[s0 >= 7]).sum() # 조건의 결과가 True인 원소들의 합
- 두 시리즈간의 연산
num_s1=pd.Series([1,2,3,4],index=['a','b','c','d'])
num_s2=pd.Series([5,6,7,8],index=['b','c','d','a'])
num_s1 + num_s2 # 시리즈간의 연산은 같은 인덱스를 찾아 연산을 진행
num_s3=pd.Series([5,6,7,8],index=['e','b','f','g'])
num_s4=pd.Series([1,2,3,4],index=['a','b','c','d'])
# 동일한 인덱스는 연산을 진행하고 나머지 인덱스는 연산처리가 불가능해서 NaN값으로 처리
num_s3 - num_s4
# values 속성을 사용해 값만을 추출해 연산을 진행하게 되면 시리즈의 형태가 사라지므로
# 동일 위치 원소들끼리 연산을 진행
# 시리즈.values는 array 형태 반환
num_s3.values - num_s4.values
딕셔너리 와 시리즈의 관계
- 시리즈 객체는 라벨(문자)에 의해 인덱싱이 가능
- 실질적으로는 라벨을 key로 가지는 딕셔너리 형과 같다고 볼 수 있음
- 딕셔너리에서 제공하는 대부분의 연산자 사용 가능
- in 연산자 : T/F
- for 루프를 통해 각 원소의 key와 value에 접근 할수 있다.
- in 연산자/ for 반복문 사용
# 인덱스가 서울 인 원소가 시리즈에 있는지 확인(in)
'서울' in s
# 인덱스가 대전 인 원소가 시리즈에 없는지 확인(not in)
'대전' not in s
# 딕셔너리의 item() 함수 시리즈에 사용 가능
s.items() # zip 객체
list(s.items())
# 시리즈 각 원소 출력
for k, v in s.items() :
print('%s=%d' % (k,v))
딕셔너리로 시리즈 만들기
- Series({key:value,key1:value1....})
- 인덱스 -> key
- 값 -> value
city = {'서울':9631482,'부산':3393191,'인천':2632035,'대전':1490158}
s=pd.Series(city)
s # 인덱스의 순서를 보장받을 수 없음
- 딕셔너리의 원소는 순서를 갖지 않는다.
- 딕셔너리로 생성된 시리즈의 원소도 순서가 보장되지 않는다.
- 만약 순서를 보장하고 싶으면 인덱스를 리스트로 지정해야 한다.
city = {'서울':9631482,'부산':3393191,'인천':2632035,'대전':1490158}
s=pd.Series(city, index=city.keys()) # ['서울', '부산', '인천', '대전']
s=pd.Series(city, index=['부산','인천','서울','대전'])
s # 딕셔너리의 부산,인천,서울,대전 키를 찾아서 그 순서대로 매칭함
시리즈 데이터의 갱신,추가, 삭제
- 인덱싱을 이용하면 딕셔너리 처럼 갱신, 추가 가능
# s 시리즈의 부산의 인구 값을 1630000으로 변경
s['부산'] = 1630000
# 시리즈내의 원소 삭제 - del 명령을 사용
del s['서울']
# 시리즈에 새로운 원소 추가
s['대구'] = 1875000
Series 함수
Series size, shape, unique, count, value_counts 함수
- size(속성) : 개수 반환
- shape(속성) : 튜플형태로 shape반환
- unique: 유일한 값만 ndarray로 반환
- count : NaN을 제외한 개수를 반환
- mean: NaN을 제외한 평균
- value_counts: NaN을 제외하고 각 값들의 빈도를 반환
s1 = pd.Series([1, 1, 2, 1, 2, 2, 2, 1, 1, 3, 3, 4, 5, 5, 7, np.NaN])
len(s1) # 16
s1.size # 16
s1.shape # (16,)
# 차원으로 표현하기 때문에 튜플형태로 출력
# 16행 이라는 의미
s1.unique() # array([ 1., 2., 3., 4., 5., 7., nan])
# nan도 하나의 값으로 보고 표현되어짐
s1.count() # 15
# nan을 제외한 원소의 개수
a = np.array([2,2,2,2,np.NaN]) # array 타입
print(a.mean()) # array에 대해 mean()함수를 적용하면 nan이 포함된 계산을 진행
# -> nan이 반환(결측치를 가지고는 계산을 진행x)
b=pd.Series(a) # 배열을 시리즈로 변경
print(b)
b.mean() # NaN 빼고 계산 (실제값만을 가지고 계산)
s1.mean() # 2.6666666666666665
s1.value_counts()
# 각 원소들에 대해 동일값의 원소끼리 그룹핑하여 개수를 세서 반환하는 함수
# 개수가 많은거 부터 표현됨
날짜 자동 생성 : date_range
# 날짜 인덱스를 이용하여 시리즈 만들기
# 날짜 표시 : '년-월-일' 형태의 문자열로 표시
index_date = ['2018-10-07','2018-10-08','2018-10-09','2018-10-10']
s4 = pd.Series([200,195,np.nan,205],index = index_date)
type(s4.index) # pandas.core.indexes.base.Index
type(s4.index[0]) # str
- 판다스 패키지의 date_range 함수 (날짜생성)
- pd.date_range(start=None, end=None, periods=None, freq='D')
- start : 시작날짜/ end= 끝날짜 / periods = 날짜 생성기간/ fref = 날짜 생성 주기
- start는 필수 옵션/end나 periods는 둘 중 하나가 있어야 함/ freq는 기본 Day로 설정
pd.date_range(start='2018-10-01', end='2018-10-20')
# DatatimeIndex 반환
# dtype='datetime64[ns]'
pd.date_range(start='2018-10-01', end='2018-10-20', freq='d')
# freq='D' 기본값
pd.date_range(start='2018-10-01', end='2018-10-20', freq='3D') # 3일씩 증가
pd.date_range(start='2018-10-01', end='2018-10-20', freq='w')
# 2018-10-01일을 기준으로 1주일씩 증가하는 날짜
# 1주 시작일 일요일을 표시
# 2018년 10월 1일 - 월요일
# 2018년 10월 1일 이후 일요일 날짜 4개 생성
pd.date_range(start='2018-10-01', periods=4, freq='w')
# 2018-10-01일 이후 월의 마지막 날짜 4개 생성
pd.date_range(start='2018-10-01', periods=4, freq='m')
pd.date_range(start='2018-10-01', periods=4, freq='M')
pd.date_range(start='2018-10-01', periods=12, freq='2BM')
# '2BM' 업무일 기준 2개월 간격 월말 주기
pd.date_range(start='2018-10-01', periods=4, freq='QS')
# 분기 시작일 기준
pd.date_range(start='2018-10-01', periods=4, freq='AS')
# 2018년 10월 1일 이후 연도 시작일 4개 생성
pd.date_range(start='2018-01-01', periods=4, freq='AS')
- 판다스 패키지의 date_range 함수 (시간생성)
pd.date_range(start='2018-01-20 08:00', periods=10, freq='H')
pd.date_range(start='2018-01-20 08:00', periods=10, freq='BH')
# 업무시간 기준 9 to 5로 설정
pd.date_range(start='2018-01-20 08:00', periods=10, freq='30min')
pd.date_range(start='2018-01-20 08:00', periods=10, freq='10S')
728x90
'프로그래밍 > Python' 카테고리의 다른 글
[Python] 리스트안에 특정 값 개수 세기 (0) | 2022.08.18 |
---|---|
[Pandas] 데이터 프레임 열 추가/ 갱신/ 삭제 (0) | 2022.08.18 |
[Pandas] 데이터 프레임 컬럼명 변경 (0) | 2022.08.18 |
jupyter notebook 상태바 사용 (0) | 2022.08.17 |
이름이 비슷한 같은 형식의 파일 여러개 한번에 읽어오는 방법 (0) | 2022.08.16 |