Pandas 알아보기
Pandas란
- 판다스(Pandas)는 파이썬 데이터 처리를 위한 라이브러리
- 파이썬을 이용한 데이터 분석과 같은 작업에서 필수 라이브러리로 알려짐
- 버전은 1.4.2 사용
- Numpy기반으로 만듬
Pandas 특징
- 부동 소수점이 아닌 데이터 / 부동 소수점 데이터에서도 결측 데이터(NaN)를 쉽게 처리
- 크기 변이성 : DataFrame 및 고차원 객체에서 열을 삽입 및 삭제 가능
- 자동 및 명시적 : 객체를 라벨 집합에 명시적으로 정렬하거나, 사용자가 라벨을 무시하고 Series, DataFrame 등의 계산에서 자동으로 데이터 조정 가능
- 데이터 세트에서 집계 및 변환을 위한 분할, 적용, 결합 작업을 수행할 수 있는 group-by 함수 제공
- 누락된 데이터 또는 다른 Python 및 Numpy 데이터 구조에서 서로 다른 인덱싱 데이터를 DataFrame 개체로 쉽게 변환
- 대용량 데이터 세트의 지능형 라벨 기반 슬라이싱, 고급 인덱싱 및 부분 집합 구하기 가능
- 직관적인 데이터 세트 병합 및 결합
- 데이터 세트의 유연한 재구성 및 피벗
- 축의 계층적 라벨링(눈금당 여러 개의 라벨을 가질 수 있음)
- 플랫 파일(CSV 및 구분), Excel 파일, 데이터베이스 로딩 및 초고속 HDF5 형식의 데이터 저장/로드에 사용되는 강력한 IO도구
- 시계열 특정 기능 : 날짜 범위 생성 및 주파수 변환, 무빙 윈도우 통계, 날짜 이동 및 지연
패키지 가져오기
기본적으로 pandas는 pd로 로드합니다.
import pandas as pd
import numpy as np
import pandas as pd
객체 생성
Series 객체
class pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
- data : array-like, Iterable, dict, scalar value Series에 저장될 데이터
- index : array-like, index 데이터와 길이가 동일해야 합니다. 데이터가 dict면 key값이 인덱스로 사용
- dtype : str, numpy.dtype, ExtensionDtype, optional 출력 Series의 데이터 유형입니다. 지정하지 않으면 data 에서 가져옴
- name : str, optional Series의 이름
- copy : bool ( defalut False ) 입력 데이터를 복사, Series 또는 1d ndarray 입력에만 영향은 줌
# Series 생성
a = pd.Series([1,3,5, np.nan, 6,8]) # list
s = pd.Series({1 : 'a', 2 : 'b', 3 : 'c'}) # dict
'list',a ,'-'*40,'dict',s
output
('list',
0 1.0
1 3.0
2 5.0
3 NaN
4 6.0
5 8.0
dtype: float64,
'----------------------------------------',
'dict',
1 a
2 b
3 c
dtype: object)
'a' , a.values, '-'*40,'s' , s.values
('a',
array([ 1., 3., 5., nan, 6., 8.]),
'----------------------------------------',
's',
array(['a', 'b', 'c'], dtype=object))
'a' , a.index,'-'*40, 's' , s.index
('a',
RangeIndex(start=0, stop=6, step=1),
'----------------------------------------',
's',
Int64Index([1, 2, 3], dtype='int64'))
index
# dict의 index 적용 방식
d = {'a' : 1, 'b' : 2, 'c': 3, 1 : 'a', 2 : 'b', 3 : 'c'}
s = pd.Series(data={1 : 'a', 2 : 'b', 3 : 'c'}, index=['a','b','c']) # dict
a = pd.Series(data=d, index=['a','b','c'])
's', s, '-'*40, 'a', a
('s',
a NaN
b NaN
c NaN
dtype: object,
'----------------------------------------',
'a',
a 1
b 2
c 3
dtype: object)
인덱스는 사전의 key값으로 먼저 빌드됩니다. 이 후 시리즈는 주어진 인덱스 값으로 다시 인덱싱되므로 결과적으로 모든 NaN을 얻습니다.
a[1]
2
a[1:3]
b 2
c 3
dtype: object
copy
# copy는 Series 또는 1d ndarray 입력에만 영향
r = [1,2]
s = pd.Series(r, copy=False)
# s = pd.Series(r, copy=True)
s.iloc[0] = 999
r , '-'*40, s
([1, 2],
'----------------------------------------',
0 999
1 2
dtype: int64)
r = np.array([1,2])
s = pd.Series(r, copy=False)
# s = pd.Series(r, copy=True)
s.iloc[0] = 999
r , '-'*40, s
(array([999, 2]),
'----------------------------------------',
0 999
1 2
dtype: int32)
DataFrame 객체
class pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=None)
- data : ndarray, Iterable, dict, DataFrame dict에 인덱스가 정의된 Series가 포함되어 있으면 인덱스에 따라 정렬
- index : Index, array-like 기본값은 RangeIndex로 설정됨
- columns : Index, array-like 기본값은 RangeIndex로 설정됨, dict와 같은 데이터일 경우 key값이 사용
- dtype : dtype ( default None ) 강제할 데이터 유형, 단일 dtype만 허용
- copy : bool or None ( default None ) 입력에서 데이터를 복사 dict 데이터의 경우 기본값은 Ture DataFrame 또는 2d ndarray 입력의 경우 기본값은 False
dates = pd.date_range("20220519", periods=6)
dates
DatetimeIndex(['2022-05-19', '2022-05-20', '2022-05-21', '2022-05-22',
'2022-05-23', '2022-05-24'],
dtype='datetime64[ns]', freq='D')
df = pd.DataFrame(np.random.rand(6, 4), index=dates, columns=list("ABCD"))
df
A | B | C | D | |
---|---|---|---|---|
2022-05-19 | 0.808475 | 0.890518 | 0.128044 | 0.098173 |
2022-05-20 | 0.661341 | 0.678233 | 0.864386 | 0.141144 |
2022-05-21 | 0.700547 | 0.812976 | 0.643775 | 0.209882 |
2022-05-22 | 0.830046 | 0.173761 | 0.883834 | 0.492513 |
2022-05-23 | 0.039317 | 0.212549 | 0.953871 | 0.627317 |
2022-05-24 | 0.899439 | 0.478153 | 0.249467 | 0.856900 |
df.index
DatetimeIndex(['2022-05-19', '2022-05-20', '2022-05-21', '2022-05-22',
'2022-05-23', '2022-05-24'],
dtype='datetime64[ns]', freq='D')
df.columns
Index(['A', 'B', 'C', 'D'], dtype='object')
# columns 출력
df['A']
2022-05-19 0.808475
2022-05-20 0.661341
2022-05-21 0.700547
2022-05-22 0.830046
2022-05-23 0.039317
2022-05-24 0.899439
Freq: D, Name: A, dtype: float64
# 인덱싱
df[1:3]
A | B | C | D | |
---|---|---|---|---|
2022-05-20 | 0.661341 | 0.678233 | 0.864386 | 0.141144 |
2022-05-21 | 0.700547 | 0.812976 | 0.643775 | 0.209882 |
df2 = pd.DataFrame(
{
"A": 1.0,
"B": pd.Timestamp("20130102"),
"C": pd.Series(1, index=list(range(4)), dtype="float32"),
"D": np.array([3] * 4, dtype="int32"),
"E": pd.Categorical(["test", "train", "test", "train"]),
"F": "foo",
}
)
df2
A | B | C | D | E | F | |
---|---|---|---|---|---|---|
0 | 1.0 | 2013-01-02 | 1.0 | 3 | test | foo |
1 | 1.0 | 2013-01-02 | 1.0 | 3 | train | foo |
2 | 1.0 | 2013-01-02 | 1.0 | 3 | test | foo |
3 | 1.0 | 2013-01-02 | 1.0 | 3 | train | foo |
Index 객체
클래스 | 설명 |
---|---|
Index | 일반적인 index 객체이며, Numpy 배열 형식으로 축의 이름 표현 |
Int64Index | 정수 값을 위한 Index |
MultiIndex | 단일 축에 여러 단계 색인을 표현하는 계층적 Index 객체 |
DatetimeIndex | Numpy의 datetime64 타입으로 타임스탬프 저장 |
PeriodIndex | 기간 데이터를 위한 Index |
idx = pd.Index([2,4,6,8,10])
idx
Int64Index([2, 4, 6, 8, 10], dtype='int64')
Index 객체 연산
| 연산자 | 메소드 | 설명 |
|:—|:—:|:—|
| |append
|객체를 추가한 새로운 index 반환|
||difference
|차집합 반환|
|&
|intersection
|교집합 반환|
| \|
|union
|합집합 반환|
| | isin
|index가 존재하는지 여부를 boolean 배열로 반환|
| | delete
|index가 삭제된 새로운 index 반환|
| |drop
|값이 삭제된 새로운 index 반환|
| |insert
| index가 추가된 새로운 index 반환
| |is_monotonic
| index가 단조성을 가지면 True|
| |is_unique
| 중복되는 index가 없다면 True|
| |unique
| index에서 중복되는 요소를 제거하고 유일한 값만 반환|
idx1 = pd.Index([1, 2, 4, 6, 8])
idx2 = pd.Index([2, 4, 6, 8, 10])
print(idx1.append(idx2))
print(idx1.difference(idx2))
print(idx1.intersection(idx2))
print(idx1 & idx2)
print(idx1.union(idx2))
print(idx1 | idx2)
print(idx1.delete(0))
print(idx1.drop(1))
print(idx1 ^ idx2)
Int64Index([1, 2, 4, 6, 8, 2, 4, 6, 8, 10], dtype='int64')
Int64Index([1], dtype='int64')
Int64Index([2, 4, 6, 8], dtype='int64')
Int64Index([2, 4, 6, 8], dtype='int64')
Int64Index([1, 2, 4, 6, 8, 10], dtype='int64')
Int64Index([1, 2, 4, 6, 8, 10], dtype='int64')
Int64Index([2, 4, 6, 8], dtype='int64')
Int64Index([2, 4, 6, 8], dtype='int64')
Int64Index([1, 10], dtype='int64')
C:\Users\ADMINI~1\AppData\Local\Temp/ipykernel_24540/674068743.py:6: FutureWarning: Index.__and__ operating as a set operation is deprecated, in the future this will be a logical operation matching Series.__and__. Use index.intersection(other) instead
print(idx1 & idx2)
C:\Users\ADMINI~1\AppData\Local\Temp/ipykernel_24540/674068743.py:8: FutureWarning: Index.__or__ operating as a set operation is deprecated, in the future this will be a logical operation matching Series.__or__. Use index.union(other) instead
print(idx1 | idx2)
C:\Users\ADMINI~1\AppData\Local\Temp/ipykernel_24540/674068743.py:11: FutureWarning: Index.__xor__ operating as a set operation is deprecated, in the future this will be a logical operation matching Series.__xor__. Use index.symmetric_difference(other) instead
print(idx1 ^ idx2)
인덱싱(Indexing)
reindex : https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reindex.html
Series 인덱싱
s = pd.Series(['a', 'b', 'c', 'd', 'e'],
index =[1,3,5,7,9])
s
1 a
3 b
5 c
7 d
9 e
dtype: object
s.iloc[1]
'b'
s.iloc[2:4]
5 c
7 d
dtype: object
s.reindex(range(10))
0 NaN
1 a
2 NaN
3 b
4 NaN
5 c
6 NaN
7 d
8 NaN
9 e
dtype: object
s.reindex(range(10), method='bfill') # bfill NaN을 다음값으로 변경
0 a
1 a
2 b
3 b
4 c
5 c
6 d
7 d
8 e
9 e
dtype: object
DataFrame 인덱싱
df = pd.DataFrame(np.random.randn(6,4), columns=list("ABCD"))
df
A | B | C | D | |
---|---|---|---|---|
0 | 0.872294 | 1.039292 | 0.515796 | 1.703427 |
1 | -0.260745 | -0.358807 | -0.665951 | -0.290013 |
2 | 1.344122 | -0.090225 | -0.163477 | 1.295620 |
3 | 0.116401 | 0.736589 | 0.209972 | -0.144976 |
4 | -1.369338 | -1.019989 | -0.674734 | -0.807702 |
5 | 1.359826 | 0.947344 | -1.451632 | -0.629882 |
df['A']
0 0.872294
1 -0.260745
2 1.344122
3 0.116401
4 -1.369338
5 1.359826
Name: A, dtype: float64
df.A
0 0.872294
1 -0.260745
2 1.344122
3 0.116401
4 -1.369338
5 1.359826
Name: A, dtype: float64
df['E'] = (df.A + df.B)
df.E
0 1.911586
1 -0.619552
2 1.253898
3 0.852990
4 -2.389327
5 2.307170
Name: E, dtype: float64
df.values
array([[ 0.87229448, 1.03929152, 0.51579579, 1.70342731, 1.911586 ],
[-0.26074461, -0.35880692, -0.66595116, -0.29001319, -0.61955153],
[ 1.34412241, -0.0902246 , -0.16347724, 1.29562007, 1.25389781],
[ 0.1164011 , 0.7365891 , 0.2099718 , -0.14497633, 0.85299019],
[-1.36933775, -1.019989 , -0.67473422, -0.80770171, -2.38932675],
[ 1.3598259 , 0.94734392, -1.45163242, -0.62988224, 2.30716981]])
# 전치
df.T
0 | 1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|---|
A | 0.872294 | -0.260745 | 1.344122 | 0.116401 | -1.369338 | 1.359826 |
B | 1.039292 | -0.358807 | -0.090225 | 0.736589 | -1.019989 | 0.947344 |
C | 0.515796 | -0.665951 | -0.163477 | 0.209972 | -0.674734 | -1.451632 |
D | 1.703427 | -0.290013 | 1.295620 | -0.144976 | -0.807702 | -0.629882 |
E | 1.911586 | -0.619552 | 1.253898 | 0.852990 | -2.389327 | 2.307170 |
df.loc[:2, :'C']
A | B | C | |
---|---|---|---|
0 | 0.872294 | 1.039292 | 0.515796 |
1 | -0.260745 | -0.358807 | -0.665951 |
2 | 1.344122 | -0.090225 | -0.163477 |
df.iloc[:3,:3]
A | B | C | |
---|---|---|---|
0 | 0.872294 | 1.039292 | 0.515796 |
1 | -0.260745 | -0.358807 | -0.665951 |
2 | 1.344122 | -0.090225 | -0.163477 |
#조건
df.loc[(df.E > 0)]
A | B | C | D | E | |
---|---|---|---|---|---|
0 | 0.872294 | 1.039292 | 0.515796 | 1.703427 | 1.911586 |
2 | 1.344122 | -0.090225 | -0.163477 | 1.295620 | 1.253898 |
3 | 0.116401 | 0.736589 | 0.209972 | -0.144976 | 0.852990 |
5 | 1.359826 | 0.947344 | -1.451632 | -0.629882 | 2.307170 |
df.loc[(df.C < 0) & (df.D > 0)]
A | B | C | D | E | |
---|---|---|---|---|---|
2 | 1.344122 | -0.090225 | -0.163477 | 1.29562 | 1.253898 |
다중 인덱싱(Multi Indexing)
- 1차원의 Series와 2차원의 DataFrame 객체, 3차원 이상의 고차원 데이터 처리
- 단일 인덱스 내에 여러 인덱스를 포함하는 다중 인덱싱
다중 인덱스 Series
df
A | B | C | D | E | |
---|---|---|---|---|---|
0 | 0.872294 | 1.039292 | 0.515796 | 1.703427 | 1.911586 |
1 | -0.260745 | -0.358807 | -0.665951 | -0.290013 | -0.619552 |
2 | 1.344122 | -0.090225 | -0.163477 | 1.295620 | 1.253898 |
3 | 0.116401 | 0.736589 | 0.209972 | -0.144976 | 0.852990 |
4 | -1.369338 | -1.019989 | -0.674734 | -0.807702 | -2.389327 |
5 | 1.359826 | 0.947344 | -1.451632 | -0.629882 | 2.307170 |
idx = [(1, 10), (1, 100),
(2, 10), (2, 100),
(3, 10), (3, 100),
(4, 10), (4, 100),
(5, 10), (5, 100),]
pop = ['ten', 'hun',
'ten', 'hun',
'ten', 'hun',
'ten', 'hun',
'ten', 'hun',]
s = pd.Series(pop, index=idx)
s
(1, 10) ten
(1, 100) hun
(2, 10) ten
(2, 100) hun
(3, 10) ten
(3, 100) hun
(4, 10) ten
(4, 100) hun
(5, 10) ten
(5, 100) hun
dtype: object
midx = pd.MultiIndex.from_tuples(idx)
midx
MultiIndex([(1, 10),
(1, 100),
(2, 10),
(2, 100),
(3, 10),
(3, 100),
(4, 10),
(4, 100),
(5, 10),
(5, 100)],
)
s = s.reindex(midx)
s
1 10 ten
100 hun
2 10 ten
100 hun
3 10 ten
100 hun
4 10 ten
100 hun
5 10 ten
100 hun
dtype: object
s[:, 10]
1 ten
2 ten
3 ten
4 ten
5 ten
dtype: object
s[2]
10 ten
100 hun
dtype: object
#unstack() 다중 인덱싱으로 만든 Series를 Data Frame으로 변환
mdf = s.unstack()
mdf
10 | 100 | |
---|---|---|
1 | ten | hun |
2 | ten | hun |
3 | ten | hun |
4 | ten | hun |
5 | ten | hun |
#stack() Data Frame을 다중 인덱싱을 가진 Series로 변환
mdf.stack()
1 10 ten
100 hun
2 10 ten
100 hun
3 10 ten
100 hun
4 10 ten
100 hun
5 10 ten
100 hun
dtype: object
t = ['십', '백',
'십', '백',
'십', '백',
'십', '백',
'십', '백',]
mdf = pd.DataFrame({'영어' : s,
'한글' : t})
mdf
영어 | 한글 | ||
---|---|---|---|
1 | 10 | ten | 십 |
100 | hun | 백 | |
2 | 10 | ten | 십 |
100 | hun | 백 | |
3 | 10 | ten | 십 |
100 | hun | 백 | |
4 | 10 | ten | 십 |
100 | hun | 백 | |
5 | 10 | ten | 십 |
100 | hun | 백 |
다중 인덱스 생성
df = pd.DataFrame(np.random.randn(6,3),
index=[['a', 'a', 'b', 'b', 'c', 'c'], [1, 2, 1, 2, 1, 2]],
columns=['c1', 'c2', 'c3'])
df
c1 | c2 | c3 | ||
---|---|---|---|---|
a | 1 | 0.996944 | 0.395115 | -0.913726 |
2 | 0.559534 | 0.408693 | -0.878460 | |
b | 1 | 1.170443 | -0.842821 | -0.332734 |
2 | 0.492504 | -0.458053 | -1.017160 | |
c | 1 | -0.781801 | 0.449425 | -0.243633 |
2 | 1.177329 | 0.025979 | 0.593342 |
# array로 가져오기
pd.MultiIndex.from_arrays([['a','a','b','b','c','c'], [1, 2, 1, 2, 1, 2]])
MultiIndex([('a', 1),
('a', 2),
('b', 1),
('b', 2),
('c', 1),
('c', 2)],
)
#곱으로 나타내기
pd.MultiIndex.from_product([['a', 'b', 'c'], [1, 2]])
MultiIndex([('a', 1),
('a', 2),
('b', 1),
('b', 2),
('c', 1),
('c', 2)],
)
# 같은 위치로 나타내기
pd.MultiIndex(levels=[['a', 'b', 'c'], [1, 2,]],
codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]])
MultiIndex([('a', 1),
('a', 2),
('b', 1),
('b', 2),
('c', 1),
('c', 2)],
)
s.index.names = ['숫자', '영어']
s
숫자 영어
1 10 ten
100 hun
2 10 ten
100 hun
3 10 ten
100 hun
4 10 ten
100 hun
5 10 ten
100 hun
dtype: object
idx = pd.MultiIndex.from_product([['a', 'b', 'c'], [1, 2]],
names=['name1', 'name2'])
cols = pd.MultiIndex.from_product([['c1', 'c2', 'c3'], [1, 2]],
names=['col_name1', 'col_name2'])
data = np.round(np.random.randn(6,6), 2)
mdf = pd.DataFrame(data, index=idx, columns=cols)
mdf
col_name1 | c1 | c2 | c3 | ||||
---|---|---|---|---|---|---|---|
col_name2 | 1 | 2 | 1 | 2 | 1 | 2 | |
name1 | name2 | ||||||
a | 1 | -0.53 | 0.64 | 1.04 | 0.58 | -0.89 | -1.00 |
2 | 1.23 | 0.77 | -1.17 | 0.70 | -0.54 | -0.68 | |
b | 1 | -1.87 | -0.03 | 0.26 | -0.48 | -0.93 | -1.56 |
2 | 0.45 | 2.95 | -0.06 | -0.91 | -0.37 | -0.34 | |
c | 1 | -1.72 | -2.43 | -0.48 | -0.31 | -0.88 | -1.08 |
2 | -1.50 | 1.72 | -0.61 | 1.03 | 0.80 | 0.62 |
인덱싱 및 슬라이싱
mdf
col_name1 | c1 | c2 | c3 | ||||
---|---|---|---|---|---|---|---|
col_name2 | 1 | 2 | 1 | 2 | 1 | 2 | |
name1 | name2 | ||||||
a | 1 | -0.53 | 0.64 | 1.04 | 0.58 | -0.89 | -1.00 |
2 | 1.23 | 0.77 | -1.17 | 0.70 | -0.54 | -0.68 | |
b | 1 | -1.87 | -0.03 | 0.26 | -0.48 | -0.93 | -1.56 |
2 | 0.45 | 2.95 | -0.06 | -0.91 | -0.37 | -0.34 | |
c | 1 | -1.72 | -2.43 | -0.48 | -0.31 | -0.88 | -1.08 |
2 | -1.50 | 1.72 | -0.61 | 1.03 | 0.80 | 0.62 |
mdf['c2', 1]
name1 name2
a 1 1.04
2 -1.17
b 1 0.26
2 -0.06
c 1 -0.48
2 -0.61
Name: (c2, 1), dtype: float64
mdf.loc[:, ('c2', 1)]
name1 name2
a 1 1.04
2 -1.17
b 1 0.26
2 -0.06
c 1 -0.48
2 -0.61
Name: (c2, 1), dtype: float64
mdf.iloc[:3, :4]
col_name1 | c1 | c2 | |||
---|---|---|---|---|---|
col_name2 | 1 | 2 | 1 | 2 | |
name1 | name2 | ||||
a | 1 | -0.53 | 0.64 | 1.04 | 0.58 |
2 | 1.23 | 0.77 | -1.17 | 0.70 | |
b | 1 | -1.87 | -0.03 | 0.26 | -0.48 |
# IndexSlice 이용하기
idx_slice = pd.IndexSlice
mdf.loc[idx_slice[:, 2], idx_slice[:, 2]]
#IndexSlice는 [a,b] 이면 a부터 b까지 b를 포함한다.
col_name1 | c1 | c2 | c3 | |
---|---|---|---|---|
col_name2 | 2 | 2 | 2 | |
name1 | name2 | |||
a | 2 | 0.77 | 0.70 | -0.68 |
b | 2 | 2.95 | -0.91 | -0.34 |
c | 2 | 1.72 | 1.03 | 0.62 |
idx_slice[:,2]
(slice(None, None, None), 2)
Leave a comment