Series(시리즈)
Polars는 두 가지 주요 데이터 구조를 제공합니다. 핵심 데이터 구조는 Series와 DataFrame입니다. Series
는 1차원 배열과 유사한 구조이며, DataFrame
은 여러 컬럼을 가진 2차원 테이블 형태의 데이터 구조입니다. 또한 Panel
이라는 3차원 데이터 구조도 제공됩니다. 이러한 데이터 구조를 통해 다양한 형태의 데이터를 쉽게 조작하고 분석할 수 있습니다.
1. Series(시리즈) 란?
Series(시리즈)
는 Polars의 1차원 데이터 배열 구조로, 시리즈명, 인덱스(묵시적 인덱스, Implicit Index)와 값으로 이루어진 데이터 구조입니다.
- 시리즈명 : 시리즈의 이름
- 인덱스 : Polars에서 자동으로 생성하는 인덱스로 값과 매핑된 고유한 행 번호
- 값 : 해당 인덱스의 데이터 값
Series는 리스트나 배열과 유사하지만, 인덱스를 지정해 데이터를 더 쉽게 조작할 수 있습니다. NumPy의 ndarray를 기반으로 하여 인덱스를 생성하고 원하는 자리를 지정해 데이터에 접근할 수 있습니다. 또한 Series 내의 모든 요소는 같은 데이터 타입(예: int, string 등)을 가져야 합니다.
2. Series 생성
먼저 리스트로 Series를 생성하고 Series 구조를 간단히 살펴보도록 하겠습니다.
import polars as pl
s = pl.Series("a", [1, 2, 3, 4, 5])
print(s)
import polars as pl
s = pl.Series("a", [1, 2, 3, 4, 5])
print(s)
Series는 시리즈명과 값
으로 이루어져 있습니다. 기본적으로 인덱스는 0부터 시작하고 타입은 정수형입니다. Series의 데이터 값은 리스트에 포함된 값들로 설정됩니다.
pl.Series(’시리즈명’, 값)
: Series를 정의할 수 있습니다.- 시리즈명 : DataFrame에서 사용될 때 열 이름으로 사용됩니다. 생략할 경우 빈 문자열로 설정됩니다.
- 값 : Array 형태의 1차원 데이터
shape: (5,)
Series: 'a' [i64]
[
1
2
3
4
5
]
shape: (5,)
Series: 'a' [i64]
[
1
2
3
4
5
]
2.1 데이터 타입 확인
생성한 Series의 데이터 타입을 확인해보도록 하겠습니다.
print(s.dtype)
print(s.dtype)
Int64
Int64
Series 생성할 때에 데이터 유형을 지정할 수 있습니다.
s2 = pl.Series("a", [1, 2, 3, 4, 5], dtype=pl.Float32)
print(s2)
s2 = pl.Series("a", [1, 2, 3, 4, 5], dtype=pl.Float32)
print(s2)
- dtype: Series의 데이터 타입입니다. 따로 dtype을 설정하지 않으면 데이터 타입을 유추합니다.
shape: (5,)
Series: 'a' [f32]
[
1.0
2.0
3.0
4.0
5.0
]
shape: (5,)
Series: 'a' [f32]
[
1.0
2.0
3.0
4.0
5.0
]
2.2 형변환
데이터 타입을 변경(형변환)을 하시려면 cast를 사용합니다.
print(s2.cast(int))
print(s2.cast(int))
- cast(dtype) : 데이터 타입을 변경합니다. 데이터 타입 종류는 int, float, str, bool 등이 있습니다.
shape: (5,)
Series: 'a' [i64]
[
1
2
3
4
5
]
shape: (5,)
Series: 'a' [i64]
[
1
2
3
4
5
]
이번에는 시리즈명을 따로 지정하지 않고 생성해보도록 하겠습니다.
s3 = pl.Series([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(s3)
s3 = pl.Series([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(s3)
시리즈명을 따로 지정하지 않으면 빈 문자열로 지정되는 것을 확인할 수 있습니다.
shape: (9,)
Series: '' [i64]
[
1
2
3
4
5
6
7
8
9
]
shape: (9,)
Series: '' [i64]
[
1
2
3
4
5
6
7
8
9
]
2.3 Series 이름 확인 및 변경
시리즈명을 확인할 때는 name를 사용합니다.
print(s3.name)
print(s3.name)
s3 시리즈 명이 빈칸이므로 아무것도 출력되지 않습니다.
s3 시리즈 명이 빈칸이므로 아무것도 출력되지 않습니다.
시리즈명을 변경할 때는 alias(’변경할 텍스트’) 또는 rename(’변경할 텍스트’)으로 변경이 가능합니다.
print(s3.alias("a"))
print(s3.rename("b"))
print(s3.alias("a"))
print(s3.rename("b"))
shape: (9,)
Series: 'a' [i64]
[
1
2
3
4
5
6
7
8
9
]
shape: (9,)
Series: 'b' [i64]
[
1
2
3
4
5
6
7
8
9
]
shape: (9,)
Series: 'a' [i64]
[
1
2
3
4
5
6
7
8
9
]
shape: (9,)
Series: 'b' [i64]
[
1
2
3
4
5
6
7
8
9
]
2.4 Series 형태
Series의 형태를 확인하고 싶은 경우에는 shape를 사용합니다.
print(s3.shape)
print(s3.shape)
(9,)
(9,)
차원을 재구성합니다.
print(s3.reshape((3, 3)))
print(s3.reshape((3, 3)))
- reshape(차원의 크기): 튜플 형태의 차원 크기입니다. 차원에 -1이 사용되면 차원이 유추됩니다.
shape: (3,)
Series: '' [list[i64]]
[
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
]
shape: (3,)
Series: '' [list[i64]]
[
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
]
explode 함수를 사용하여 차원을 분해할 수 있습니다. 다시 말하자면, 1차원으로 만들 수 있습니다.
print(s3.explode())
print(s3.explode())
shape: (9,)
Series: '' [i64]
[
1
2
3
4
5
6
7
8
9
]
shape: (9,)
Series: '' [i64]
[
1
2
3
4
5
6
7
8
9
]
2.5 고유값 확인
Series의 고유값을 확인할 수 있습니다.
s4 = pl.Series("a", [1, 3, 2, 2, 3])
print(s4.unique())
s4 = pl.Series("a", [1, 3, 2, 2, 3])
print(s4.unique())
shape: (3,)
Series: 'a' [i64]
[
1
2
3
]
shape: (3,)
Series: 'a' [i64]
[
1
2
3
]
maintain_order 매개변수를 True로 주시면 데이터 순서를 유지하게 됩니다.
print(s4.unique(maintain_order=True))
print(s4.unique(maintain_order=True))
shape: (3,)
Series: 'a' [i64]
[
1
3
2
]
shape: (3,)
Series: 'a' [i64]
[
1
3
2
]
n_unique는 Series의 고유값 개수를 계산합니다.
print(s4.n_unique())
print(s4.n_unique())
3
3
unique_counts는 나타나는 순서대로 고유값 발생 횟수를 반환합니다.
s5 = pl.Series("s", ["a", "b", "b", "c", "c", "c"])
print(s5.unique_counts())
s5 = pl.Series("s", ["a", "b", "b", "c", "c", "c"])
print(s5.unique_counts())
shape: (3,)
Series: 's' [u32]
[
1
2
3
]
shape: (3,)
Series: 's' [u32]
[
1
2
3
]
value_counts는 고유값 발생 횟수를 계산합니다.
print(s5.value_counts())
print(s5.value_counts())
shape: (3, 2)
┌─────┬───────┐
│ s ┆ count │
│ --- ┆ --- │
│ str ┆ u32 │
╞═════╪═══════╡
│ b ┆ 2 │
│ c ┆ 3 │
│ a ┆ 1 │
└─────┴───────┘
shape: (3, 2)
┌─────┬───────┐
│ s ┆ count │
│ --- ┆ --- │
│ str ┆ u32 │
╞═════╪═══════╡
│ b ┆ 2 │
│ c ┆ 3 │
│ a ┆ 1 │
└─────┴───────┘
이때, 출력을 count별로 정렬하고 count 열 이름을 사용자 지정할 수 있습니다.
print(s5.value_counts(sort=True, name='s_count'))
print(s5.value_counts(sort=True, name='s_count'))
- sort: 카운트별로 내림차순으로 정렬합니다.
- False(기본값)로 설정하면 출력 순서는 무작위입니다.
- name: 고유값 개수 열 이름 설정
shape: (3, 2)
┌─────┬───────┐
│ s ┆ count │
│ --- ┆ --- │
│ str ┆ u32 │
╞═════╪═══════╡
│ c ┆ 3 │
│ b ┆ 2 │
│ a ┆ 1 │
└─────┴───────┘
shape: (3, 2)
┌─────┬───────┐
│ s ┆ count │
│ --- ┆ --- │
│ str ┆ u32 │
╞═════╪═══════╡
│ c ┆ 3 │
│ b ┆ 2 │
│ a ┆ 1 │
└─────┴───────┘
3. RangeIndex
Series를 생성할 때, Polars에서는 자동으로 RangeIndex
가 생성됩니다. 예를 들어, pl.Series([1, 2, 3, 4, 5])
를 생성하면, RangeIndex(start=0, stop=5, step=1)
가 자동으로 생성됩니다. RangeIndex
는 메모리를 절약하고 효율적으로 사용하기 위해 구현된 것이며, 이로 인해 대규모 데이터 처리를 빠르게 할 수 있습니다.
import numpy as np
data = np.arange(0, 50, 10)
print(data)
import numpy as np
data = np.arange(0, 50, 10)
print(data)
[ 0 10 20 30 40]
[ 0 10 20 30 40]
s6 = pl.Series(data)
print(s6)
s6 = pl.Series(data)
print(s6)
shape: (5,)
Series: '' [i64]
[
0
10
20
30
40
]
shape: (5,)
Series: '' [i64]
[
0
10
20
30
40
]
4. Series의 인덱싱, 슬라이싱
4.1 Indexing
생성된 Series에서 특정 인덱스의 값을 가져와보도록 하겠습니다.
print(pl.Series(data)[0])
print(pl.Series(data)[0])
해당 시리즈의 첫 번째 값을 가져올 수 있습니다.
0
0
4.2. Slicing
:
연산자를 사용하여 여러 개의 값을 한꺼번에 가져올 수도 있습니다.
# [start:stop:step]
print(pl.Series(data)[0:3])
print(pl.Series(data)[::-1]) # 역순
# [start:stop:step]
print(pl.Series(data)[0:3])
print(pl.Series(data)[::-1]) # 역순
shape: (3,)
Series: '' [i64]
[
0
10
20
]
shape: (5,)
Series: '' [i64]
[
40
30
20
10
0
]
shape: (3,)
Series: '' [i64]
[
0
10
20
]
shape: (5,)
Series: '' [i64]
[
40
30
20
10
0
]
print(pl.Series(data)[0:3])
은 0번부터 2번(stop 인덱스 3에서 1을 뺀 값)까지의 인덱스 값을 가져올 수 있습니다.
print(pl.Series(data)[::-1])
은 해당 시리즈의 값들을 역순으로 출력해줍니다.
4.3 Boolean indexing
Series에서는 불리언을 이용해 조건에 맞는 데이터만 필터링할 수 있습니다.
print(s6.filter(s6>20))
print(s6.filter(s6>20))
shape: (2,)
Series: '' [i64]
[
30
40
]
shape: (2,)
Series: '' [i64]
[
30
40
]
s6.filter(s6>20)
는 시리즈에서 20을 초과하는 값들을 가진 시리즈를 출력합니다.
print(s6>20)
print(s6>20)
shape: (5,)
Series: '' [bool]
[
false
false
false
true
true
]
shape: (5,)
Series: '' [bool]
[
false
false
false
true
true
]
print(s6>20)
은 각 값이 20을 초과하는 지 여부를 부울값(True, False)로 확인할 수 있습니다.
5. Series 객체의 접근 메서드
5.1 Fancy Indexing (팬시 인덱싱)
Fancy indexing은 NumPy와 같은 배열(array)의 특정 위치에 접근하는 방법입니다. Polars에서는 gather, gather_every, item, slice 메서드를 사용하여 팬시 인덱싱을 수행할 수 있습니다.
print(s3)
print(s3)
shape: (9,)
Series: '' [i64]
[
1
2
3
4
5
6
7
8
9
]
shape: (9,)
Series: '' [i64]
[
1
2
3
4
5
6
7
8
9
]
- gather(인덱스) : 시리즈의 특정 행(row)에 접근하는 메서드입니다. 다시 말해, 인덱스(행 번호)를 기반으로 데이터 값을 읽을 수 있습니다. 인덱스가 없는 경우에는 오류가 뜨게 됩니다.
print(s3.gather(1)) print(s3.gather([1,3,5]))
print(s3.gather(1)) print(s3.gather([1,3,5]))
s3.gather(1)
은 인덱스가 1인 데이터 값을 가져올 수 있습니다.s3.gather([1,3,5])
은 인덱스가 1,3,5인 데이터 값을 가져올 수 있습니다.
음수 인덱스를 이용해 시리즈 객체의 마지막 데이터에 접근할 수 있습니다.shape: (1,) Series: '' [i64] [ 2 ] shape: (3,) Series: '' [i64] [ 2 4 6 ]
shape: (1,) Series: '' [i64] [ 2 ] shape: (3,) Series: '' [i64] [ 2 4 6 ]
print(s3.gather(-1))
print(s3.gather(-1))
shape: (1,) Series: '' [i64] [ 9 ]
shape: (1,) Series: '' [i64] [ 9 ]
- gather_every(n): 시리즈의 시작 인덱스부터 n번째 행(row)에 접근하는 메서드입니다.
print(s3.gather_every(2))
print(s3.gather_every(2))
n이 시리즈 길이보다 큰 경우 첫번째 인덱스의 데이터 값을 출력합니다.shape: (5,) Series: '' [i64] [ 1 3 5 7 9 ]
shape: (5,) Series: '' [i64] [ 1 3 5 7 9 ]
print(s3.gather_every(10))
print(s3.gather_every(10))
shape: (1,) Series: '' [i64] [ 1 ]
shape: (1,) Series: '' [i64] [ 1 ]
- item(인덱스): 시리즈의 특정 행(row)에 접근하는 메서드입니다. 다시 말해, 인덱스(행 번호)를 기반으로 데이터 값을 읽을 수 있습니다. 인덱스가 없는 경우에는 오류가 뜨게 됩니다.
gather과 유사하지만, 시리즈를 하나의 스칼라 값으로 가져올 수 있습니다.
인덱스가 1인 데이터 값을 가져올 수 있습니다.
print(s3.item(1))
print(s3.item(1))
음수 인덱스를 이용해 시리즈 객체의 마지막 데이터에 접근할 수 있습니다.2
2
print(s3.item(-1))
print(s3.item(-1))
시리즈의 길이가 1일 때, 인덱스가 제공되지 않으면 첫번째 요소를 출력합니다.9
9
s1 = pl.Series("a", [1]) print(s1.item())
s1 = pl.Series("a", [1]) print(s1.item())
1
1
- slice(시작 인덱스, 길이): 시작 인덱스부터 지정한 길이 만큼 데이터를 가져올 수 있습니다.
print(s)
print(s)
shape: (5,) Series: 'a' [i64] [ 1 2 3 4 5 ]
shape: (5,) Series: 'a' [i64] [ 1 2 3 4 5 ]
인덱스가 1인 데이터 값부터 시작하여 3개의 데이터를 가져옵니다.print(s.slice(1, 3))
print(s.slice(1, 3))
길이를 설정하지 않는 경우 시작 인덱스부터 마지막까지의 데이터를 가져옵니다.shape: (3,) Series: 'a' [i64] [ 2 3 4 ]
shape: (3,) Series: 'a' [i64] [ 2 3 4 ]
print(s.slice(1))
print(s.slice(1))
인덱스가 없는 경우에는 오류가 뜨지 않고 빈 시리즈가 반환됩니다.shape: (4,) Series: 'a' [i64] [ 2 3 4 5 ]
shape: (4,) Series: 'a' [i64] [ 2 3 4 5 ]
print(s.slice(6))
print(s.slice(6))
shape: (0,) Series: 'a' [i64] [ ]
shape: (0,) Series: 'a' [i64] [ ]
6. 결측값(NaN, None, Null) 처리
결측값(Missing Value)은 값이 없거나 데이터를 수집하거나 처리하는 과정에서 누락된 값을 말합니다.
Numpy에서는 결측값을 None
, Pandas에서는 NaN(Not a Number)
로 처리했었습니다. Polars에서는 결측값을 Null
로 표시합니다.
6.1 NaN
- 자료형이 Float
- 수치형 연산에서 오류가 발생하지 않지만 결과 값이 NaN이 됨
6.2 None
- 자료형이 None
- 수치형 연산에서 오류가 발생
6.3 Null
- 자료형이 Null
- 수치형 연산에서 오류가 발생
import numpy as np
import pandas as pd
import polars as pl
data = [1, 2, 3, None]
print(np.array(data)) # None - 수치 연산 시 error
print(pd.Series(data)) # NaN - 수치 연산 처리가 용이
print(pl.Series(data)) # null - 수치 연산 시 error
import numpy as np
import pandas as pd
import polars as pl
data = [1, 2, 3, None]
print(np.array(data)) # None - 수치 연산 시 error
print(pd.Series(data)) # NaN - 수치 연산 처리가 용이
print(pl.Series(data)) # null - 수치 연산 시 error
[1 2 3 None]
0 1.0
1 2.0
2 3.0
3 NaN
dtype: float64
shape: (4,)
Series: '' [i64]
[
1
2
3
null
]
[1 2 3 None]
0 1.0
1 2.0
2 3.0
3 NaN
dtype: float64
shape: (4,)
Series: '' [i64]
[
1
2
3
null
]
# print(np.array(data)[3] + 100)
# print(np.array(data)[3] * 100)
# print(np.array(data)[3] * 0)
# print(np.array(data)[3] + 100)
# print(np.array(data)[3] * 100)
# print(np.array(data)[3] * 0)
error
error
error
error
error
error
print(pd.Series(data)[3] + 100)
print(pd.Series(data)[3] * 100)
print(pd.Series(data)[3] * 0)
print(pd.Series(data)[3] + 100)
print(pd.Series(data)[3] * 100)
print(pd.Series(data)[3] * 0)
nan
nan
nan
nan
nan
nan
# print(pl.Series(data)[3] + 100)
# print(pl.Series(data)[3] * 100)
# print(pl.Series(data)[3] * 0)
# print(pl.Series(data)[3] + 100)
# print(pl.Series(data)[3] * 100)
# print(pl.Series(data)[3] * 0)
error
error
error
error
error
error
집계 함수를 이용하면 에러가 나지 않고 연산을 수행할 수 있습니다.
s = pl.Series(data)
print(s)
print(s.sum())
print(s.max())
print(s.min())
s = pl.Series(data)
print(s)
print(s.sum())
print(s.max())
print(s.min())
shape: (4,)
Series: '' [i64]
[
1
2
3
null
]
6
3
1
shape: (4,)
Series: '' [i64]
[
1
2
3
null
]
6
3
1
data2 = [1, 2, 3, np.nan]
s2=pl.Series(data2)
print(s2)
print(s2.sum())
print(s2.max())
print(s2.min())
data2 = [1, 2, 3, np.nan]
s2=pl.Series(data2)
print(s2)
print(s2.sum())
print(s2.max())
print(s2.min())
shape: (4,)
Series: '' [f64]
[
1.0
2.0
3.0
NaN
]
nan
3.0
1.0
shape: (4,)
Series: '' [f64]
[
1.0
2.0
3.0
NaN
]
nan
3.0
1.0
6.4 처리방법
결측값을 확인하는 방법은 is_nan()
또는 is_null()
메서드를 사용하는 것입니다. 이 메서드를 사용하면 각 원소가 결측값인지 아닌지를 확인할 수 있습니다.
- is_null(), is_nan(): 결측값 확인 (결측 이면 True , 결측이 아니면 False)
- is_not_null(), is_not_nan(): 결측값 확인 (결측 이면 False , 결측이 아니면 True)
- null_count() : 결측값의 개수를 계산합니다.
- drop_nulls(), drop_nans(): 결측값을 삭제
- fill_null(value, strategy, limit), fill_nan(value): 결측을 value이나 지정된 값(strategy)으로 채워 넣음
- value : 결측값을 채울 때 사용되는 값
- strategy 매개변수에는 ‘forward’(앞에 있는 값), ‘backward’(뒤에 있는 값), ‘min’(최솟값), ‘max’(최댓값), ‘mean’(평균), ‘zero’(0), ‘one’(1) 값이 들어갈 수 있습니다. ex) fill_null(strategy='forward')
- limit : strategy 매개변수가 ‘forward’ 또는 ‘backward’ 인 경우 채울 연속 null 값의 수
print(s.is_null())
print(s.is_null())
shape: (4,)
Series: '' [bool]
[
false
false
false
true
]
shape: (4,)
Series: '' [bool]
[
false
false
false
true
]
print(s2.is_nan())
print(s2.is_nan())
shape: (4,)
Series: '' [bool]
[
false
false
false
true
]
shape: (4,)
Series: '' [bool]
[
false
false
false
true
]
data = [1, 2, 3, None, None, None, None]
s = pl.Series(data)
print(s.is_null())
print(s.is_null().sum())
data = [1, 2, 3, None, None, None, None]
s = pl.Series(data)
print(s.is_null())
print(s.is_null().sum())
shape: (7,)
Series: '' [bool]
[
false
false
false
true
true
true
true
]
4
shape: (7,)
Series: '' [bool]
[
false
false
false
true
true
true
true
]
4
data2 = [1, 2, 3, np.nan, np.nan, np.nan, np.nan]
s2 = pl.Series(data2)
print(s2.is_nan())
print(s2.is_nan().sum())
data2 = [1, 2, 3, np.nan, np.nan, np.nan, np.nan]
s2 = pl.Series(data2)
print(s2.is_nan())
print(s2.is_nan().sum())
shape: (7,)
Series: '' [bool]
[
false
false
false
true
true
true
true
]
4
shape: (7,)
Series: '' [bool]
[
false
false
false
true
true
true
true
]
4
print(s.is_not_null())
print(s.is_not_null().sum())
print(s.is_not_null())
print(s.is_not_null().sum())
shape: (7,)
Series: '' [bool]
[
true
true
true
false
false
false
false
]
3
shape: (7,)
Series: '' [bool]
[
true
true
true
false
false
false
false
]
3
print(s2.is_not_nan())
print(s2.is_not_nan().sum())
print(s2.is_not_nan())
print(s2.is_not_nan().sum())
shape: (7,)
Series: '' [bool]
[
true
true
true
false
false
false
false
]
3
shape: (7,)
Series: '' [bool]
[
true
true
true
false
false
false
false
]
3
print(s.null_count())
print(s.null_count())
4
4
print(s.drop_nulls())
print(s.drop_nulls())
shape: (3,)
Series: '' [i64]
[
1
2
3
]
shape: (3,)
Series: '' [i64]
[
1
2
3
]
print(s2.drop_nans())
print(s2.drop_nans())
shape: (3,)
Series: '' [f64]
[
1.0
2.0
3.0
]
shape: (3,)
Series: '' [f64]
[
1.0
2.0
3.0
]
print(s.fill_null(0))
print(s.fill_null(0))
shape: (7,)
Series: '' [i64]
[
1
2
3
0
0
0
0
]
shape: (7,)
Series: '' [i64]
[
1
2
3
0
0
0
0
]
print(s.fill_null(strategy="forward", limit=2))
print(s.fill_null(strategy="forward", limit=2))
shape: (7,)
Series: '' [i64]
[
1
2
3
3
3
null
null
]
shape: (7,)
Series: '' [i64]
[
1
2
3
3
3
null
null
]
print(s.fill_null(strategy="mean"))
print(s.fill_null(strategy="mean"))
shape: (7,)
Series: '' [i64]
[
1
2
3
2
2
2
2
]
shape: (7,)
Series: '' [i64]
[
1
2
3
2
2
2
2
]
print(s2.fill_nan(0))
print(s2.fill_nan(0))
shape: (7,)
Series: '' [f64]
[
1.0
2.0
3.0
0.0
0.0
0.0
0.0
]
shape: (7,)
Series: '' [f64]
[
1.0
2.0
3.0
0.0
0.0
0.0
0.0
]
drop_nulls(), drop_nans(), fill_null(), fill_nan() 메서드는 원본에 바로 반영이 안되니 변수에 저장해주셔야 합니다.
# s = s.drop_nulls()
# s2 = s2.drop_nans()
# s = s.fill_null(0)
# s2 = s2.fill_nan(0)
# s = s.drop_nulls()
# s2 = s2.drop_nans()
# s = s.fill_null(0)
# s2 = s2.fill_nan(0)
추가로 알아두면 좋은 정보!
a = np.arange(1, 10).reshape(3, 3)
print(a)
a = np.arange(1, 10).reshape(3, 3)
print(a)
[[1 2 3]
[4 5 6]
[7 8 9]]
[[1 2 3]
[4 5 6]
[7 8 9]]
a[0][1] = np.nan # integer에서는 nan을 사용할 수 없다.
a[0][1] = np.nan # integer에서는 nan을 사용할 수 없다.
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-15-10bef5bd968c> in <module>
----> 1 a[0][1] = np.nan
ValueError: cannot convert float NaN to integer
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-15-10bef5bd968c> in <module>
----> 1 a[0][1] = np.nan
ValueError: cannot convert float NaN to integer
7. Series 연산
s = pl.Series([100, 200, 300, 400, 500])
ss = pl.Series([10, 20, 30, 40, 50])
s = pl.Series([100, 200, 300, 400, 500])
ss = pl.Series([10, 20, 30, 40, 50])
7.1 Series 산술 연산
print(s + 100)
print(s - 100)
print(s * 2)
print(s ** 2)
print(s ** 0.5)
print(s / 2)
print(s // 2)
print(s % 3)
print(s + 100)
print(s - 100)
print(s * 2)
print(s ** 2)
print(s ** 0.5)
print(s / 2)
print(s // 2)
print(s % 3)
shape: (5,)
Series: '' [i64]
[
200
300
400
500
600
]
shape: (5,)
Series: '' [i64]
[
0
100
200
300
400
]
shape: (5,)
Series: '' [i64]
[
200
400
600
800
1000
]
shape: (5,)
Series: '' [i64]
[
10000
40000
90000
160000
250000
]
shape: (5,)
Series: '' [f64]
[
10.0
14.142136
17.320508
20.0
22.36068
]
shape: (5,)
Series: '' [f64]
[
50.0
100.0
150.0
200.0
250.0
]
shape: (5,)
Series: '' [i64]
[
50
100
150
200
250
]
shape: (5,)
Series: '' [i64]
[
1
2
0
1
2
]
shape: (5,)
Series: '' [i64]
[
200
300
400
500
600
]
shape: (5,)
Series: '' [i64]
[
0
100
200
300
400
]
shape: (5,)
Series: '' [i64]
[
200
400
600
800
1000
]
shape: (5,)
Series: '' [i64]
[
10000
40000
90000
160000
250000
]
shape: (5,)
Series: '' [f64]
[
10.0
14.142136
17.320508
20.0
22.36068
]
shape: (5,)
Series: '' [f64]
[
50.0
100.0
150.0
200.0
250.0
]
shape: (5,)
Series: '' [i64]
[
50
100
150
200
250
]
shape: (5,)
Series: '' [i64]
[
1
2
0
1
2
]
print(s + ss)
print(s - ss)
print(s * ss)
print(s // ss) # integer형
print(s / ss) # float형
print(s % ss)
print(s ** 3)
print(s + ss)
print(s - ss)
print(s * ss)
print(s // ss) # integer형
print(s / ss) # float형
print(s % ss)
print(s ** 3)
shape: (5,)
Series: '' [i64]
[
110
220
330
440
550
]
shape: (5,)
Series: '' [i64]
[
90
180
270
360
450
]
shape: (5,)
Series: '' [i64]
[
1000
4000
9000
16000
25000
]
shape: (5,)
Series: '' [i64]
[
10
10
10
10
10
]
shape: (5,)
Series: '' [f64]
[
10.0
10.0
10.0
10.0
10.0
]
shape: (5,)
Series: '' [i64]
[
0
0
0
0
0
]
shape: (5,)
Series: '' [i64]
[
1000000
8000000
27000000
64000000
125000000
]
shape: (5,)
Series: '' [i64]
[
110
220
330
440
550
]
shape: (5,)
Series: '' [i64]
[
90
180
270
360
450
]
shape: (5,)
Series: '' [i64]
[
1000
4000
9000
16000
25000
]
shape: (5,)
Series: '' [i64]
[
10
10
10
10
10
]
shape: (5,)
Series: '' [f64]
[
10.0
10.0
10.0
10.0
10.0
]
shape: (5,)
Series: '' [i64]
[
0
0
0
0
0
]
shape: (5,)
Series: '' [i64]
[
1000000
8000000
27000000
64000000
125000000
]
- pow: 거듭제곱 연산 함수
print(s.pow(3))
print(s.pow(3))
shape: (5,)
Series: '' [i64]
[
1000000
8000000
27000000
64000000
125000000
]
shape: (5,)
Series: '' [i64]
[
1000000
8000000
27000000
64000000
125000000
]
7.2 집계 함수
- count: null이 아닌 데이터 개수 구하는 함수
- min: 최소값 구하는 함수
- max: 최대값 구하는 함수
- mean: 평균 구하는 함수
- median: 중앙값 구하는 함수
- mode: 최빈값 구하는 함수
- sum: 시리즈의 합계를 구하는 함수
- std: 표준편차 구하는 함수
- var: 분산 구하는 함수
- sqrt: 제곱근 구하는 함수
- describe: 기초 통계를 한 번에 볼 수 있는 함수
print(s.count())
print(s.min())
print(s.max())
print(s.mean())
print(s.median())
print(s.mode())
print(s.sum())
print(s.std())
print(s.var())
print(s.sqrt())
print(s.count())
print(s.min())
print(s.max())
print(s.mean())
print(s.median())
print(s.mode())
print(s.sum())
print(s.std())
print(s.var())
print(s.sqrt())
5
100
500
300.0
300.0
shape: (5,)
Series: '' [i64]
[
500
300
200
400
100
]
1500
158.11388300841898
25000.0
shape: (5,)
Series: '' [f64]
[
10.0
14.142136
17.320508
20.0
22.36068
]
5
100
500
300.0
300.0
shape: (5,)
Series: '' [i64]
[
500
300
200
400
100
]
1500
158.11388300841898
25000.0
shape: (5,)
Series: '' [f64]
[
10.0
14.142136
17.320508
20.0
22.36068
]
print(s[2:].sum())
print(s[2:].sum())
1200
1200
print(s[2:])
print(s[2:])
shape: (3,)
Series: '' [i64]
[
300
400
500
]
shape: (3,)
Series: '' [i64]
[
300
400
500
]
print(s.describe())
print(s.describe())
shape: (9, 2)
┌────────────┬────────────┐
│ statistic ┆ value │
│ --- ┆ --- │
│ str ┆ f64 │
╞════════════╪════════════╡
│ count ┆ 5.0 │
│ null_count ┆ 0.0 │
│ mean ┆ 300.0 │
│ std ┆ 158.113883 │
│ min ┆ 100.0 │
│ 25% ┆ 200.0 │
│ 50% ┆ 300.0 │
│ 75% ┆ 400.0 │
│ max ┆ 500.0 │
└────────────┴────────────┘
shape: (9, 2)
┌────────────┬────────────┐
│ statistic ┆ value │
│ --- ┆ --- │
│ str ┆ f64 │
╞════════════╪════════════╡
│ count ┆ 5.0 │
│ null_count ┆ 0.0 │
│ mean ┆ 300.0 │
│ std ┆ 158.113883 │
│ min ┆ 100.0 │
│ 25% ┆ 200.0 │
│ 50% ┆ 300.0 │
│ 75% ┆ 400.0 │
│ max ┆ 500.0 │
└────────────┴────────────┘
숫자가 아닌 데이터들의 기초통계량입니다.
s2 = pl.Series(["aa", "aa", None, "bb", "cc"])
print(s2.describe())
s2 = pl.Series(["aa", "aa", None, "bb", "cc"])
print(s2.describe())
shape: (4, 2)
┌────────────┬───────┐
│ statistic ┆ value │
│ --- ┆ --- │
│ str ┆ str │
╞════════════╪═══════╡
│ count ┆ 4 │
│ null_count ┆ 1 │
│ min ┆ aa │
│ max ┆ cc │
└────────────┴───────┘
shape: (4, 2)
┌────────────┬───────┐
│ statistic ┆ value │
│ --- ┆ --- │
│ str ┆ str │
╞════════════╪═══════╡
│ count ┆ 4 │
│ null_count ┆ 1 │
│ min ┆ aa │
│ max ┆ cc │
└────────────┴───────┘
8. 데이터 결합
-
concatenate: 배열 결합
import numpy as np a = np.arange(10).reshape(2, 5) b = np.arange(10).reshape(2, 5) c = np.arange(10).reshape(2, 5) print(a)
import numpy as np a = np.arange(10).reshape(2, 5) b = np.arange(10).reshape(2, 5) c = np.arange(10).reshape(2, 5) print(a)
[[0 1 2 3 4] [5 6 7 8 9]]
[[0 1 2 3 4] [5 6 7 8 9]]
print(np.concatenate([a, b, c]))
print(np.concatenate([a, b, c]))
[[0 1 2 3 4] [5 6 7 8 9] [0 1 2 3 4] [5 6 7 8 9] [0 1 2 3 4] [5 6 7 8 9]]
[[0 1 2 3 4] [5 6 7 8 9] [0 1 2 3 4] [5 6 7 8 9] [0 1 2 3 4] [5 6 7 8 9]]
print(np.concatenate([a, b, c], axis=1))
print(np.concatenate([a, b, c], axis=1))
[[0 1 2 3 4 0 1 2 3 4 0 1 2 3 4] [5 6 7 8 9 5 6 7 8 9 5 6 7 8 9]]
[[0 1 2 3 4 0 1 2 3 4 0 1 2 3 4] [5 6 7 8 9 5 6 7 8 9 5 6 7 8 9]]
a = pl.Series(['A', 'B', 'C', 'D', 'E']) b = pl.Series(['A', 'B', 'C', 'D', 'E']) c = pl.Series(['A', 'B', 'C', 'D', 'E']) print(a)
a = pl.Series(['A', 'B', 'C', 'D', 'E']) b = pl.Series(['A', 'B', 'C', 'D', 'E']) c = pl.Series(['A', 'B', 'C', 'D', 'E']) print(a)
shape: (5,) Series: '' [str] [ "A" "B" "C" "D" "E" ]
shape: (5,) Series: '' [str] [ "A" "B" "C" "D" "E" ]
print(np.concatenate([a, b, c]))
print(np.concatenate([a, b, c]))
['A' 'B' 'C' 'D' 'E' 'A' 'B' 'C' 'D' 'E' 'A' 'B' 'C' 'D' 'E']
['A' 'B' 'C' 'D' 'E' 'A' 'B' 'C' 'D' 'E' 'A' 'B' 'C' 'D' 'E']
-
append: 마지막 행에 데이터를 추가
s1 = pl.Series("a", [1, 2, 3]) s2 = pl.Series("b", [4, 5]) print(s1.append(s2))
s1 = pl.Series("a", [1, 2, 3]) s2 = pl.Series("b", [4, 5]) print(s1.append(s2))
shape: (5,) Series: 'a' [i64] [ 1 2 3 4 5 ]
shape: (5,) Series: 'a' [i64] [ 1 2 3 4 5 ]
-
extend: 데이터 프레임이나 시리즈, 배열 결합
s1 = pl.Series("a", [1, 2, 3]) s2 = pl.Series("b", [4, 5]) print(s1.extend(s2))
s1 = pl.Series("a", [1, 2, 3]) s2 = pl.Series("b", [4, 5]) print(s1.extend(s2))
shape: (5,) Series: 'a' [i64] [ 1 2 3 4 5 ]
shape: (5,) Series: 'a' [i64] [ 1 2 3 4 5 ]
append와 extend의 차이점
- append는 다른 Series의 청크를 현재 Series의 청크에 추가합니다.
- extend는 다른 Series의 데이터를 기본 메모리 위치에 직접 추가합니다.
extend를 사용하면 때때로 비용이 많이 드는 재할당이 발생할 수 있습니다. 하지만 재할당이 발생하지 않으면, 결과 데이터 구조에는 추가 청크가 없어 쿼리 속도가 빨라집니다.
- 한 번 추가한 후 쿼리를 수행하려는 경우 extend를 선호합니다. 예를 들어, 온라인 작업 중에 n개의 행을 추가하고 쿼리를 다시 실행하는 경우입니다.
- 여러 번 추가한 후 쿼리를 수행하려는 경우에는 append를 선호합니다. 예를 들어, 여러 파일을 읽어와서 하나의 시리즈에 저장하려는 경우입니다. 후자의 경우, 리청크로 추가 작업 순서를 마무리하세요.
9. 기타 함수
print(s4)
print(s4)
shape: (5,)
Series: 'a' [i64]
[
1
3
2
2
3
]
shape: (5,)
Series: 'a' [i64]
[
1
3
2
2
3
]
9.1 sample(n)
시리즈에서 무작위로 샘플을 추출합니다.
print(s4.sample(2))
print(s4.sample(2))
- n: 추출할 샘플의 수입니다. 기본값은 1입니다.
- seed : 난수 생성을 위한 시드값입니다. seed를 설정하지 않으면 셔플이 호출될 때마다 무작위 시드가 생성됩니다.
- with_replacement: 값을 두 번 이상 샘플링할 수 있도록 허용합니다.
- shuffle: 샘플링된 데이터의 순서를 섞습니다.
shape: (2,)
Series: 'a' [i64]
[
2
1
]
shape: (2,)
Series: 'a' [i64]
[
2
1
]
print(s4.sample(2, seed=0))
print(s4.sample(2, seed=0))
shape: (2,)
Series: 'a' [i64]
[
3
2
]
shape: (2,)
Series: 'a' [i64]
[
3
2
]
print(s4.sample(2, with_replacement=True))
print(s4.sample(2, with_replacement=True))
shape: (2,)
Series: 'a' [i64]
[
2
2
]
shape: (2,)
Series: 'a' [i64]
[
2
2
]
print(s4.sample(3, shuffle=True))
print(s4.sample(3, shuffle=True))
shape: (3,)
Series: 'a' [i64]
[
2
2
1
]
shape: (3,)
Series: 'a' [i64]
[
2
2
1
]
9.2 shuffle
시리즈 모든 요소를 무작위로 섞습니다.
print(s4.shuffle())
print(s4.shuffle())
shape: (5,)
Series: 'a' [i64]
[
2
1
3
2
3
]
shape: (5,)
Series: 'a' [i64]
[
2
1
3
2
3
]
print(s4.shuffle(seed=1))
print(s4.shuffle(seed=1))
shape: (5,)
Series: 'a' [i64]
[
3
2
3
1
2
]
shape: (5,)
Series: 'a' [i64]
[
3
2
3
1
2
]
9.3 sort
시리즈 요소들을 정렬합니다. 시리즈에 null 값이 있는 경우 null 값은 맨 상단에 위치합니다.
print(s4.sort())
print(s4.sort())
shape: (5,)
Series: 'a' [i64]
[
1
2
2
3
3
]
shape: (5,)
Series: 'a' [i64]
[
1
2
2
3
3
]
print(s4.sort(descending=True, in_place=True))
print(s4.sort(descending=True, in_place=True))
- descending=True : 내림차순으로 정렬합니다.
- in_place : 원본에 반영합니다.
shape: (5,)
Series: 'a' [i64]
[
3
3
2
2
1
]
shape: (5,)
Series: 'a' [i64]
[
3
3
2
2
1
]
9.4 reverse
시리즈를 역순으로 반환합니다.
print(s1)
print(s1)
shape: (5,)
Series: 'a' [i64]
[
1
2
3
4
5
]
shape: (5,)
Series: 'a' [i64]
[
1
2
3
4
5
]
print(s1.reverse())
print(s1.reverse())
shape: (5,)
Series: 'a' [i64]
[
5
4
3
2
1
]
shape: (5,)
Series: 'a' [i64]
[
5
4
3
2
1
]
9.5 rank
동점이 있는 경우를 고려하여 데이터에 순위를 부여합니다.
- method: 순위를 지정합니다.
- average(기본값): 동점인 값들에게 할당될 수 있는 순위의 평균이 각 값에 할당됩니다.
- min: 동점인 모든 값에 할당될 수 있는 순위 중 최소값이 각 값에 할당되며, 경쟁 순위라고도 불립니다.
- max : 동점인 모든 값에 할당될 수 있는 순위 중 최대값이 각 값에 할당됩니다.
- dense : 'min'과 비슷하지만, 동점인 요소들에게 같은 순위를 부여한 후 그 다음 순위를 건너뛰지 않고 바로 다음 번호로 할당하여 연속적인 순위를 만듭니다.
- ordinal : 모든 값에 고유한 순위가 부여되며, 시리즈에서 값이 발생하는 순서에 따라 부여됩니다.
- random : 'ordinal'와 유사하지만, 동점인 값들의 순위를 무작위로 할당합니다.
- descending=True: 내림차순으로 순위를 지정합니다.
- seed: method="random"인 경우, 난수 생성의 시작점을 설정할 수 있어 seed 값을 사용합니다.
print(s4)
print(s4)
shape: (5,)
Series: 'a' [i64]
[
3
3
2
2
1
]
shape: (5,)
Series: 'a' [i64]
[
3
3
2
2
1
]
print(s4.rank())
print(s4.rank())
shape: (5,)
Series: 'a' [f64]
[
4.5
4.5
2.5
2.5
1.0
]
shape: (5,)
Series: 'a' [f64]
[
4.5
4.5
2.5
2.5
1.0
]
print(s4.rank(descending=True))
print(s4.rank(descending=True))
shape: (5,)
Series: 'a' [f64]
[
5.0
1.5
3.5
3.5
1.5
]
shape: (5,)
Series: 'a' [f64]
[
5.0
1.5
3.5
3.5
1.5
]
print(s4.rank("ordinal"))
print(s4.rank("ordinal"))
shape: (5,)
Series: 'a' [u32]
[
4
5
2
3
1
]
shape: (5,)
Series: 'a' [u32]
[
4
5
2
3
1
]
print(s4.rank("random", seed=123))
print(s4.rank("random", seed=123))
shape: (5,)
Series: 'a' [u32]
[
1
5
2
3
4
]
shape: (5,)
Series: 'a' [u32]
[
1
5
2
3
4
]
9.6 set(조건, 변경할 값)
조건에 맞는 값들을 변경할 값으로 재설정합니다.
print(s1)
print(s1)
shape: (5,)
Series: 'a' [i64]
[
1
2
3
4
5
]
shape: (5,)
Series: 'a' [i64]
[
1
2
3
4
5
]
print(s1.set(s1 == 2, 10))
print(s1.set(s1 == 2, 10))
shape: (5,)
Series: 'a' [i64]
[
1
10
3
4
5
]
shape: (5,)
Series: 'a' [i64]
[
1
10
3
4
5
]
9.7 scatter(인덱스 위치, 변경할 값)
인덱스 위치에 있는 값을 다른 값을 변경합니다.
print(s1)
print(s1)
shape: (5,)
Series: 'a' [i64]
[
1
2
3
4
5
]
shape: (5,)
Series: 'a' [i64]
[
1
2
3
4
5
]
print(s1.scatter(2, 2))
print(s1.scatter(2, 2))
shape: (5,)
Series: 'a' [i64]
[
1
2
2
4
5
]
shape: (5,)
Series: 'a' [i64]
[
1
2
2
4
5
]
9.8 replace(값, 대체할 값)
시리즈의 특정 값을 다른 값으로 대체할 때 사용합니다. 값을 변경할 때, 대체되지 않은 값은 변경되지 않은 상태로 유지됩니다.
print(s1.replace(2, 20))
print(s1.replace(2, 20))
- value: 시리즈의 값
- new_value: 대체할 값, 길이는 value의 길이와 일치하거나 길이가 1이어야 합니다
shape: (5,)
Series: 'a' [i64]
[
1
20
20
4
5
]
shape: (5,)
Series: 'a' [i64]
[
1
20
20
4
5
]
리스트에 교체할 값과 대체할 값을 순서대로 작성하여 여러 값을 교체할 수 있습니다.
print(s1.replace([2, 4], [20, 40]))
print(s1.replace([2, 4], [20, 40]))
shape: (5,)
Series: 'a' [i64]
[
1
20
20
40
5
]
shape: (5,)
Series: 'a' [i64]
[
1
20
20
40
5
]
또한 replace(old=Series(mapping.keys()), new=Series(mapping.values()))
처럼 시리즈로 값과 대체 값을 작성할 수 있습니다.
값을 대체할 때 딕셔너리 형태로 원본 값과 대체할 값의 쌍을 전달할 수 있습니다. 또한, 딕셔너리에 명시되지 않은 값들을 일괄적으로 다른 값으로 대체하고 싶다면 'default' 매개변수를 사용하여 기본값을 지정할 수 있습니다.
mapping = {2: 100, 3: 200}
print(s1.replace(mapping, default=-1))
mapping = {2: 100, 3: 200}
print(s1.replace(mapping, default=-1))
- default: 대체되지 않은 값을 설정합니다. 기본값은 원래 값을 유지합니다.
shape: (5,)
Series: 'a' [i64]
[
-1
100
100
200
-1
]
shape: (5,)
Series: 'a' [i64]
[
-1
100
100
200
-1
]
default로 다른 시리즈 설정할 수 있습니다.
default = pl.Series([0.0, 2.5, 5.0, 7.5, 10.0])
print(s1.replace(2, 100, default=default))
default = pl.Series([0.0, 2.5, 5.0, 7.5, 10.0])
print(s1.replace(2, 100, default=default))
shape: (5,)
Series: 'a' [f64]
[
0.0
100.0
100.0
7.5
10.0
]
shape: (5,)
Series: 'a' [f64]
[
0.0
100.0
100.0
7.5
10.0
]
시리즈의 값을 다른 데이터 유형으로 변경할 때, 반환되는 데이터 유형은 원래의 데이터 유형과 새로운 데이터 유형따라 반환될 데이터 유형이 결정됩니다.
print(s5)
print(s5)
shape: (6,)
Series: 's' [str]
[
"a"
"b"
"b"
"c"
"c"
"c"
]
shape: (6,)
Series: 's' [str]
[
"a"
"b"
"b"
"c"
"c"
"c"
]
mapping = {"a": 1, "b": 2, "c": 3}
print(s5.replace(mapping))
mapping = {"a": 1, "b": 2, "c": 3}
print(s5.replace(mapping))
shape: (6,)
Series: 's' [str]
[
"1"
"2"
"2"
"3"
"3"
"3"
]
shape: (6,)
Series: 's' [str]
[
"1"
"2"
"2"
"3"
"3"
"3"
]
print(s5.replace(mapping, default=None))
print(s5.replace(mapping, default=None))
shape: (6,)
Series: 's' [i64]
[
1
2
2
3
3
3
]
shape: (6,)
Series: 's' [i64]
[
1
2
2
3
3
3
]
반환될 데이터 유형을 return_dtype 매개변수를 이용하여 직접 설정할 수 있습니다.
print(s5.replace(mapping, return_dtype=pl.Float32))
print(s5.replace(mapping, return_dtype=pl.Float32))
- return_dtype: 반환될 시리즈의 데이터 유형입니다. None(기본값)으로 설정하면 데이터 유형이 자동으로 결정됩니다.
shape: (6,)
Series: 's' [f32]
[
1.0
2.0
2.0
3.0
3.0
3.0
]
shape: (6,)
Series: 's' [f32]
[
1.0
2.0
2.0
3.0
3.0
3.0
]
9.9 is_between(하한값, 상한값)
시리즈의 각 요소가 하한/상한 사이에 있는지 확인하고 bool값을 가져옵니다. 하한값이 상한값보다 크면 조건을 만족하는 값이 없으므로 결과는 False가 됩니다.
print(s1.is_between(2, 4))
print(s1.is_between(2, 4))
shape: (5,)
Series: 'a' [bool]
[
false
true
true
true
false
]
shape: (5,)
Series: 'a' [bool]
[
false
true
true
true
false
]
closed를 사용하여 하한/상한 값을 포함하거나 제외합니다.
print(s1.is_between(2, 4, closed="left"))
print(s1.is_between(2, 4, closed="left"))
- closed: 'both'(기본값), 'left', 'right', 'none'
shape: (5,)
Series: 'a' [bool]
[
false
true
true
false
false
]
shape: (5,)
Series: 'a' [bool]
[
false
true
true
false
false
]
숫자/시간 값뿐만 아니라 문자열도 사용할 수 있습니다.
s2 = pl.Series("s", ["a", "b", "c", "d", "e"])
print(s2.is_between("b", "d", closed="both"))
s2 = pl.Series("s", ["a", "b", "c", "d", "e"])
print(s2.is_between("b", "d", closed="both"))
shape: (5,)
Series: 's' [bool]
[
false
true
true
true
false
]
shape: (5,)
Series: 's' [bool]
[
false
true
true
true
false
]
9.10 is_in
시리즈의 요소가 다른 시리즈에 들어가 있는지 확인합니다.
s1 = pl.Series("a", [1, 2, 3])
s2 = pl.Series("b", [2, 4])
print(s2.is_in(s1))
s1 = pl.Series("a", [1, 2, 3])
s2 = pl.Series("b", [2, 4])
print(s2.is_in(s1))
shape: (2,)
Series: 'b' [bool]
[
true
false
]
shape: (2,)
Series: 'b' [bool]
[
true
false
]
일부 값이 하위 리스트의 요소인지 확인합니다.
s1 = pl.Series("s", [[1, 2, 3], [1, 2], [9, 10]])
s2 = pl.Series("ss", [1, 2, 3])
print(s2.is_in(s1))
s1 = pl.Series("s", [[1, 2, 3], [1, 2], [9, 10]])
s2 = pl.Series("ss", [1, 2, 3])
print(s2.is_in(s1))
shape: (3,)
Series: 'ss' [bool]
[
true
true
false
]
shape: (3,)
Series: 'ss' [bool]
[
true
true
false
]
9.11 map_elements(함수명)
시리즈의 요소에 대해 사용자 정의 함수를 매핑하여 값을 반환합니다.
s = pl.Series("a", [1, 2, 3, None, 4, 5])
print(s.map_elements(lambda x: x + 10, return_dtype=pl.Int64, skip_nulls=True))
s = pl.Series("a", [1, 2, 3, None, 4, 5])
print(s.map_elements(lambda x: x + 10, return_dtype=pl.Int64, skip_nulls=True))
- function : 사용자 지정 함수, 람다 함수
- returndtype: 출력 데이터 유형. 설정하지 않으면 함수가 반환하는 첫 번째 널이 아닌 값을 기준으로 dtype을 유추합니다. 함수가 다른 데이터 타입을 반환하는 경우 반환타입 인수를 설정해야 하며, 그렇지 않으면 오류가 납니다.
- skip_nulls: null 값은 건너뛰어서 계산합니다.
shape: (6,)
Series: 'a' [i64]
[
11
12
13
null
14
15
]
shape: (6,)
Series: 'a' [i64]
[
11
12
13
null
14
15
]
map_elements 메서드는 내장함수보다 느리게 동작하고 메모리를 더 많이 차지합니다. 내장함수는 Rust에서 실행되고, 사용자 정의 함수는 Python에서 실행됩니다.
import time
s = pl.Series("a", [3, 6, 1, 1, 6])
import time
s = pl.Series("a", [3, 6, 1, 1, 6])
-
사용자 정의함수 pow_fn()
start_time = time.time() def pow_fn(x): return x**2 s.map_elements(pow_fn,return_dtype=pl.Int64) end_time = time.time() map_elements_time = end_time - start_time print(map_elements_time) # 0.0008041858673095703
start_time = time.time() def pow_fn(x): return x**2 s.map_elements(pow_fn,return_dtype=pl.Int64) end_time = time.time() map_elements_time = end_time - start_time print(map_elements_time) # 0.0008041858673095703
-
내장함수 pow()
start_time = time.time() s.pow(2) end_time = time.time() bf_time = end_time - start_time print(bf_time) # 0.0006339550018310547
start_time = time.time() s.pow(2) end_time = time.time() bf_time = end_time - start_time print(bf_time) # 0.0006339550018310547