코딩하는 타코야끼

[Pandas] 1강_Pandas Series 본문

[T.I.L] : Today I Learned/Pandas

[Pandas] 1강_Pandas Series

가스오부시 2023. 4. 11. 14:48
728x90
반응형

1. Pandas 개요

🌓  데이터 분석과 관련된 다양한 기능을 제공하는 파이썬 패키지

  • 데이터 셋을 이용한 다양한 통계 처리 기능을 제공한다.
  • 표 형태의 데이터를 다루는데 특화된 파이썬 모듈.
    • 엑셀의 기능을 제공하는 파이썬 모듈이라고 생각하면 이해가 쉽다.
  • 표 형태의 데이터를 다루기 위한 시리즈(Series) 와 데이터프레임(DataFrame) 클래스 제공 !!!
    • Series : 1차원 자료구조를 표현
    • DataFrame : 2차원 행렬구조의 표(table)를 표현

🌓  설치

  • pip install pandas
  • conda instll pandas

🌓  공식 홈페이지


2. Series


📍 Series 개요

  • 1차원 자료구조
  • DataFrame(표)의 한 행(row)이나 한 열(column)을 표현한다.
  • 각 원소는 index와 index 이름을 가지며 그것들을 이용해 사용할 수 있다.
  • 벡터화 연산(element-wise 연산)을 지원
    • Series 객체에 연산을 하면 각각의 Series 원소들에 연산이 된다.
  • Series를 구성하는 원소들을 다루는 다양한 메소드 제공

📍 Series생성

🌓   구문

  • Series(1차원 배열형태 자료구조)
  •  배열형태(array-like) 자료구조 
    • 리스트
    • 튜플
    • 넘파이 배열(ndarray)
# 판다스 import -> 별칭은 관례적으로 pd 를 준다.
import pandas as pd
# series 생성
s1 = pd.Series([10,20,30,40,50,60]) # 리스트의 원소들을 원소로 가지는 Series를 생성.
print(s1)
>>>
0    10
1    20
2    30
3    40
4    50
5    60
dtype: int64
# Series 객체의 몇몇 속성 조회
print('데이터 타입: ', s1.dtype) #int64 -> 정수타입, 1개의 값을 64비트로 (8byte)로 저장. ->
                              # 판다스 데이터입은 numpy 의 데이터타입을 사용 -> numpy는 c의 datatype을 사용
print('전체 원소의 개수:',s1.size)# 전체 원소의 개수: 6
print('차원별 개수:', s1.shape)  # tuple , 개수: 6행
>>>
데이터 타입:  int64
전체 원소의 개수: 6
차원별 개수: (6,)

🌓  Series안의 원소(element) 접근 - Indexing과 Slicing

  • Index는 Series에 저장된 각 원소를 구분하는 식별자로 각 원소를 사용할때 사용한다. Series의 원소들은 두 종류의 index를 가진다.

1.  index (순번)

  • 자동으로 배정되는 순번.
  • 리스트나 튜플의 index와 동일하다.
  • 0 부터 1씩 증가하는 양수 index와 -1 부터 1씩 감소하는 음수 index 두가지가 붙는다. 양수 index는 앞에서 부터, 음수 index는 뒤에서 부터 붙는다.

2. index name(index이름)

  • 명시적으로 각 index에 지정하는 이름
  • 딕셔너리의 key의 역할을 한다.
    • Series의 index name은 중복될 수 있다.
  • 생략하면 양수 index가 index name이 된다.
  • Index와 index name 두가지의 식별자가 붙는 것은 Series, DataFrame 동일하다.
  • Series나 DataFrame을 출력하면 나오는 index는 index name이다. 자동으로 붙는 index는 판다스 내부에서 관리된다.

🌓  Indexing

  • 한개의 원소를 식별할 때 사용한다.
  • index 순번으로 조회
    •  Series[순번] 
    •  Series.iloc[순번] 
  • index 이름으로 조회
    •  Series[index 이름] 
    •  Series.loc[index 이름] 
    • index 이름이 문자열이면 문자열(" ") 로, 정수이면 정수로 호출
      •  s['name'], s[2], s.loc['name'], s.loc[2] 
    • Series.index 이름
      • index의 이름이 파이썬 식별자 규칙에 맞을 경우 . 표기법 사용 할 수 있다..
  • Series[index]는 기본적으로 Index명으로 조회한다.
    • index 이름과 index의 타입이 다르면 알아서 처리해준다.
    • index 이름의 type이 int일 때 index(순번)으로 조회하고 싶은 경우 (index이름과 index 의 타입이 int로 같은 경우를 말한다.)
      • iloc indexer를 사용
      •  Series객체.iloc[순번] 
  • 팬시(fancy) 인덱싱 -Series[index리스트]
    • 한번에 여러개의 원소를 조회할 때 그 index들을 list로 묶어서 전달한다.
      •  series[[1,2,3]] 
s1 = pd.Series([100, 80, 90, 60], index = ['Python', "Java", 'C', "JS"])
s1
>>>
Python    100
Java       80
C          90
JS         60
dtype: int64
# 순번 - iloc indexer, 이름 - loc indexer
s2.iloc[0], s2.iloc[-4], s2.loc['Python']
>>>
(100, 100, 100)

🌓  Slicing

  • 범위로 원소들을 조회할 때 사용한다.
  • Series[start index : stop index : step]
    • start index 생략 : 0번 부터
    • stop index
      • index 순번일 경우는 포함 하지는다.
      • index 명의 경우는 포함한다.
    • stop index 생략 : 마지막 index까지
    • step 생략 : 1씩 증가
  • Slicing의 결과는 원본의 참조(View)를 반환
    • Slicing은 shallow copy를 한다. 그래서 slicing한 결과를 원소를 변경하면 slicing 했던 원본도 같이 바뀐다.
    • 원본은 변경되지 않게 하려면  slicing결과.copy() 를 이용해 deep copy를 해야 한다.
s5 = pd.Series(range(100)) # 0 ~ 99 를 원소로 가지는 시리즈
print(s5.dtype, s5.shape)
>>>
int64 (100,)
-----------
s5[10:20:5] # index로 slicing. stop이 포함안됨.
>>>
10    10
15    15
dtype: int64

🌓  shallow copy와 deep copy

  • deep copy(깊은 복사)
    • 원본과 동일한 값을 가진 새로운 객체를 만들어 반환한다. 그래서 복사본의 값을 변경해도 원본이 변경되지 않는다.
    • 파이썬 리스트는 slicing시 deep copy를 한다.
  • shallow copy(얕은 복사)
    • 원본을 반환하여 값 변경시 원본에 영향을 준다.
    • Series, DataFrame, 넘파이 배열(ndarray)은 slicing 조회 시 shallow copy한다.
  • copy( ) 메소드
    • Series, DataFrame, ndarray를 deep copy 한다.
s1 = pd.Series(range(10), index = list("zaicbrdekj"))
# slicing 결과를 변경하되 원본은 유지하려하면 copy() 해서 새로 만들어야 한다.
result2 = s1['r':'k'].copy() # deep copy
result2[0] =100000
result2
>>>
r    100000
d         6
e         7
k         8
dtype: int64

📍 벡터화 (연산)

  • Pandas의 Series나 DataFrame은 연산을 하면 원소 단위로 연산을 한다.
    • element-wise 연산 이라고도 한다.
  • Series/DataFrame과 값(scalar값)을 연산하면 각 원소들과 값을 연산한다.
  • Series끼리 또는 DataFrame끼리 연산을 하면 같은 위치의 원소끼리 연산을 한다.
    • Index 이름이 (index가 아닌) 같은 원소끼리 연산한다.
grade1 = pd.Series([100, 90, 70, 80])
grade2 = pd.Series([80, 100, 90, 100], index = ['영어', '수학','국어', '과학'])
grade3 = pd.Series([70, 80, 100, 100], index = ['영어', '수학','국어', '과학'])

# index 이름이 다른 Series
grade1 + grade2
>>>
0    NaN
1    NaN
2    NaN
3    NaN
과학   NaN
국어   NaN
수학   NaN
영어   NaN
dtype: float64
# index 이름이 같은 Series
grade2 + grade3
>>>
영어    150
수학    180
국어    190
과학    200
dtype: int64

📍 Boolean 인덱싱

  • Series의 indexing 연산자에 boolean 리스트를 넣으면 True인 index의 값들만 조회한다.
    • 원하는 조건의 값들을 조회할 때 사용한다.

  • 논리연산자의 피연산자들은 반드시 ( )로 묶어준다.
  • 파이썬과는 다르게 and, or, not 은 예약어는 사용할 수 없다.
  • Series에서특정 조건이 True인 원소들을 조회: boolean indexing특정 조건이 True인 원소들
  • index를 조회: numpy.where(boolean 연산)특정 조건이 True인 원소와 False인 원소를 각각 다른
  • 값으로 변경: numpy.where(boolean 연산, True변환값, False변환값)
  • Numpy의 ndarray도 동일
  •  
import numpy as np
# 0 ~ 1000 사이의 숫자를 100개 random 하게 생성(난수 - random value)
s20 = pd.Series(np.random.randint(0,1000,100))
# s20의 원소중 100 ~ 900 사이가 아닌 값들을 조회  **(not =>> ~)**
s20[~((s20 >= 100) & (s20 <= 900))]
>>>
19    925
24      0
35     43
41    965
42    955
48    930
51    933
58     93

📍 주요 메소드, 속성

🌓  메소드

 

  • abc 와 zxy 같은 문자열에서 min()을 사용할 경우 abc의 값이 나온다.
  • 반대로 max() 적용시 zxy의 값이 나온다.
print(s20.dtype) # series 의 데이터 타입
print(s20.size) # 원소 개수
print(s20.shape) # Series의 형태-차원별 (축 - axis) 크기
print(s20.index) # index 이름을 조회.
>>>
int64
100
(100,)
RangeIndex(start=0, stop=100, step=1)
# np.random.choice(['Python', 'Java', 'C', 'GO', 'Rust'],100)
# 특정 개수의 값으로만 구성된 자료구조 => 범주형(Categorical type)
s2 = pd.Series(np.random.choice(['Python', 'Java', 'C', 'GO', 'Rust'],100))
s2.value_counts() # sㅈ을 구성하는 범주값들의 각각의 개수
>>>
Java      24
GO        23
Python    22
Rust      16
C         15
dtype: int64

🌓  정렬

  • sort_values()
    • 값으로 정렬
  • sort_index()
    • index명으로 정렬
  • 공통 매개변수
    • ascending=False (내림차순, 기본-True:오름차순)
    • inplace=True
      • 원본 자체를 정렬
      • False(기본값): 정렬결과를 새로운 Series로 반환.
    • 결측치(NaN)는 정렬 방식과 상관없이 마지막에 나온다.
  • index 명으로 졍렬
s5 = pd.Series([20,6,-10,100,7], index=['Z', 'R', 'A', 'B', 'S'])
 # 오름차순을 기본으로 정렬 // 원본은 바뀌지 않고 새로운 파일을 만든거임.
s6 = s5.sort_index()
s5.sort_index(ascending=False) # 내림차순 정렬.
s5.sort_index(inplace=True) # 원본(s5)이 바뀜.
s5
>>>
Z     20
S      7
R      6
B    100
A    -10
dtype: int64

 

  • 값으로 정렬
s5.sort_values(ascending=False) # 내림차순
s5.sort_values(inplace=True)
s5
>>>
A    -10
R      6
S      7
Z     20
B    100
dtype: int64

📍 기술 통계량

  • 데이터셋의 데이터들의 특징을 하나의 숫자로 요약한 것.

🌓  평균

  • 전체 데이터들의 합계를 총 개수로 나눈 통계량
  • 전체 데이터셋의 데이터들은 평균값 근처에 분포되어 데이터셋의 대표값으로 사용한다.
  • 이상치(너무 크거나 작은 값)의 영향을 많이 받는다.

🌓  중앙값

  • 분포된 값들을 작은값 부터 순서대로 나열한 뒤 그 중앙에 위치한 값
  • 이상치에 영향을 받지 않아 평균대신 집단의 대표값으로 사용한다.

🌓  표준편차/분산

  • 값들이 흩어져있는 상태(분포)를 추정하는 통계량으로 분포된 값들이 평균에서 부터 얼마나 떨어져 있는지를 나타내는 통계량.
  • 각 데이터가 평균으로 부터 얼마나 차이가 있는지를 편차(Deviation)라고 한다. ()평균−데이터
  • 평균−데이터
  • 분산 : 편차 제곱의 합을 총 개수로 나눈 값

  • 표준편차
    • 분산의 제곱근
    • 분산은 원래 값에 제곱을 했으므로 다시 원래 단위로 계산한 값.

🌓  최빈값(mode)

  • 데이터 셋에서 가장 많이 있는 값.

🌓  분위수(Quantile)

  • 데이터의 크기 순서에 따른 위치값
    • 데이터셋을 크기순으로 정렬한뒤 N등분했을 때 특정 위치에서의 값 (단면)
    • N등분한 특정위치의 값들 통해 전체 데이터셋을 분포를 파악한다.
    • 대표적인 분위수 : 4분위, 10분위, 100분위
  • 데이터의 분포를 파악할 때 사용
  • 이상치 중 극단값들을 찾을 때 사용 (4분위수)

print(s5.max(), s5.min())       # 최대,최소
print(s5.idxmax(), s5.idxmin()) # 최대 / 최소값의 index 이름.
print(s5.sum(), s5.mean(), s40.median()) # 합계, 평균, 중앙값
print(s5.std(), s5.var())       # 표준편차, 분산
>>>
100 -10
B A
123 24.6 7.0
43.47182995918161 1889.8000000000002
# 분위수 
s7 = pd.Series(np.random.randint(100,1000, 100))

# 4분위 : 4등분 했을때 나뉘는 위치의 값
s60.quantile(q=[0.25,0.5,0.75])
>>>
0.25    318.50
0.50    542.00
0.75    842.75
dtype: float64

📍 결측치 (Missing Value, Not Available)

🌓 개요

  • 결측지: 모르는 값, 수집이 안된값, 현재 가지고 있지 않은 값.
  • 판다스에서 결측치
    • None, numpy.nan, numpy.NAN
    • 결측치는 float 타입으로 처리한다.
      • 많은 value중 float 타입의 값이 하나 있으면 모든 값들은 float타입으로 나온다.

🌓  결측치 확인

  • 각 함수/메소드는 각 원소별로 결측치인지 확인해서 결과를 반환한다.
  • Numpy
    • np.isnan(배열)
  • Series/DataFrame
    • Series/DataFrame객체.isnull(), 또는 .isna()
    • Series/DataFrame객체, notnull(), 또는 .notna()
# 결측지가 추가됨으로서 dtype이 int 가 아닌 float으로 나옴.
s = pd.Series([10, 2, 40, 7, 20, np.nan, 50, np.nan, 10])
s
>>>
0    10.0
1     2.0
2    40.0
3     7.0
4    20.0
5     NaN
6    50.0
7     NaN
8    10.0
dtype: float64
# 결측지 확인
result = s.isnull() # 원소별로 결측이 인지(True) 아닌지(False) 체크
result
>>>
0    False
1    False
2    False
3    False
4    False
5     True
6    False
7     True
8    False
dtype: bool
1

🌓  결측치 처리

  • 제거
    • dropna()
  • 다른값으로 대체
    • fillna()
    • 평균, 중앙값, 최빈값을 주로 사용
# 결측치를 처리
# 제거
s.dropna() # 결측치를 제거한 결과를 새 Series에 담아서 반환 (S는 변경안됨) 원본 변경 -> inplace = True
>>>
0    10.0
1     2.0
2    40.0
3     7.0
4    20.0
6    50.0
8    10.0
dtype: float64
--------------------
s2 = s.copy()
s2.dropna(inplace=True)
s2
>>>
0    10.0
1     2.0
2    40.0
3     7.0
4    20.0
6    50.0
8    10.0
dtype: float64
# 결측치를 다른 값으로 대체
s.fillna(1000000)
>>>
0         10.0
1          2.0
2         40.0
3          7.0
4         20.0
5    1000000.0
6         50.0
7    1000000.0
8         10.0
dtype: float64
s.mean()  # 평균 구하기, # 판다스는 결측치를 빼고 계산한다.
s.mean(skipna=False) #결측치도 포함해서 계산.
s.sum(skipna=False)
반응형