Python특징

여러 프로그래밍 작업 중 데이터 분석과 관련한 고유의 Python특징 및 강력함에 대해 알고 있어야 합니다. 데이터 랭글링에서 기계 학습에 이르기까지 Python은 데이터 분석을 위한 사실상의 언어가 되었습니다.

하지만 데이터 분석자들이 Python이 제공하는 모든 특징들을 다 활용하고 있을까요? 그렇지 않습니다. 따라서 이번 포스팅에서는 모든 데이터 과학자가 알아야 할 12가지 Python특징 에 대해 자세히 살펴보겠습니다.

comprehensions에서 data class에 이르기까지 이러한 특징은 보다 효율적이고, 읽기 쉽고, 유지 관리 가능한 코드를 작성하는 데 많은 도움이 됩니다.


Comprehensions

Python특징 중 하나인 Comprehension은 간결하고 읽기 쉬운 방식으로 복잡한 데이터 구조를 생성할 수 있어 기계 학습 및 데이터 분석 작업에 유용한 도구입니다.

List Comprehension은 숫자 범위에서 제곱 값 리스트를 만드는 것과 같이 데이터 리스트를 생성하는 데 사용할 수 있습니다. 중첩 List Comprehension은 데이터 과학의 일반적인 전처리 작업인 다차원 배열을 평면화하는 데 사용할 수 있습니다.

# list comprehension
even = [x**2 for x in range(1, 11)]

# 중첩 list comprehension
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

flatList = [num
for row in matrix       # outer loop
for num in row]         # inner loop

print(even)
print(flatList)
-----------------------------------------------
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

♦♦♦♦♦♦♦♦♦♦♦♦♦

dictionary 및 set Comprehension는 각각 dictionary 및 data set을 만드는 데 유용합니다. 예를 들어 dictionary 및 set Comprehension을 사용하여 기계 학습 모델에서 feature name 과 해당하는 feature importance 점수의 dictionary를 만들 수 있습니다.

Generator Comprehension은 메모리에 큰 데이터 구조를 생성하는 대신 즉석에서 값을 생성하므로 큰 데이터 세트 작업에 특히 유용합니다. 이렇게 하면 성능을 개선하고 메모리 사용량을 줄이는 데 도움이 될 수 있습니다.

# dictionary comprehension
tempDictionary = {var:var ** 2 for var in range(1, 11) if var % 2 != 0}

# set comprehension
# create a set of squares of numbers from 1 to 10
tempSet = {x**2 for x in range(1, 11)}

# generator comprehension
tempGenerator = (x**2 for x in range(1, 11))

print(tempDictionary)
print(tempSet)
print(list(g for g in tempGenerator))
-------------------------------------------------------------------------
{1: 1, 3: 9, 5: 25, 7: 49, 9: 81}
{64, 1, 4, 36, 100, 9, 16, 49, 81, 25}
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]


Enumerate

enumerate는 각 요소의 인덱스를 추적하면서 시퀀스(예: 리스트 또는 튜플)를 반복할 수 있는 내장 함수로 대표적인 Python특징 중 하나입니다. 인덱스 위치를 추적하면서 개별 요소에 쉽게 접근하고 조작할 수 있으므로 데이터 세트로 작업할 때 유용할 수 있습니다.

아래 코드 예시는 enumerate를 사용하여 문자열 리스트를 반복하고 인덱스가 짝수이면 값을 출력합니다.

for idx, value in enumerate(["a", "b", "c", "d"]):
    if idx % 2 == 0:
    print(value)
-------------------------
a
c


Zip

zip은 여러 시퀀스(예: 리스트 또는 튜플)를 병렬로 반복할 수 있는 내장 함수로 고유한 Python특징 중 하나 입니다. 아래에서는 zip을 사용하여 두 개의 리스트 x와 y를 동시에 반복하고 해당 요소에 대한 작업을 수행합니다.

x = [1, 2, 3, 4]
y = [5, 6, 7, 8]

for a, b in zip(x, y):
    print(a, b, a + b, a * b) #  x와 y의 각 요소 값, 합계 및 곱 출력
------------------------------------------------------------------
1 5 6 5
2 6 8 12
3 7 10 21
4 8 12 32


Generators

Python의 generator는 모든 값을 한 번에 생성하고 메모리에 저장하는 대신 일련의 값을 생성할 수 있는 반복 가능한 유형입니다. 따라서 데이터가 한 번에 모두 처리되지 않고 작은 chunk 또는 batch로 처리되기 때문에 메모리에 맞지 않는 대규모 데이터 세트로 작업하는 데 유용합니다.

아래에서는 생성기 함수를 사용하여 피보나치 수열에서 처음 n개의 숫자를 생성합니다. yield 키워드는 전체 시퀀스를 한 번에 생성하는 대신 시퀀스의 각 값을 한 번에 하나씩 생성하는 데 사용됩니다.

def fib_gen(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b
res = fib_gen(10)
print(list(r for r in res))
------------------------------------
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Lambda functions

lambda는 이름이 없고 한 줄의 코드로 정의할 수 있는 함수인 익명 함수를 만드는 데 사용되는 대표적인 Python특징 중 하나 입니다. feature engineering, 데이터 전처리 또는 모델 평가를 위해 즉석에서 사용자 지정 함수를 정의하는 데 유용합니다.

아래에서는 lambda를 사용하여 숫자 리스트에서 짝수를 필터링하는 간단한 함수를 만듭니다.

numbers = range(10)
evenNumbers = list(filter(lambda x: x % 2 == 0, numbers))

print(evenNumbers)
--------------------------------
[0, 2, 4, 6, 8]

♦♦♦♦♦♦♦♦♦♦♦♦♦

다음은 Pandas에서 람다 함수를 사용하기 위한 또 다른 단편 코드입니다.

import pandas as pd

data = {
    "salesPerson": ["Alice", "Bob", "Charlie", "David"],
    "saleAmount": [100, 200, 300, 400],
}
sale = pd.DataFrame(data)

threshold = 250
sale["aboveThreshold"] = sale["saleAmount"].apply(lambda x: True if x >= threshold else False)
sale
  salesPerson saleAmount aboveThreshold
0 Alice 100 False
1 Bob 200 False
2 Charlie 300 True
3 David 400 True


Map, filter, reduce

map, filter 및 reduce 함수는 데이터 조작 및 변환에 사용되는 세 가지 기본 제공 함수입니다. map은 iterable의 각 요소에 함수를 적용하는 데 사용되고, filter는 조건에 따라 iterable에서 요소를 선택하는 데 사용되며, reduce는 iterable의 요소 쌍에 함수를 적용하여 단일 결과를 생성하는 데 사용됩니다.

아래에서 우리는 단일 파이프라인에서 이들 모두를 사용하여 짝수의 제곱합을 계산합니다.

numbers = range(10)

# 짝수만 선택
evenNumbers = filter(lambda x: x % 2 == 0, numbers)

# 앞서 선택된 짝수의 제곱
squares = map(lambda x: x**2, evenNumbers)

# 최종 결과
from functools import reduce
sumOfSquares = reduce(lambda x, y: x + y, squares)

print(f"Sum of the squares of even numbers: {sumOfSquares}")
--------------------------------------------------------------
Sum of the squares of even numbers: 120


Any and all

any 및 all은 iterable의 일부 또는 모든 요소가 특정 조건을 충족하는지 확인할 수 있는 내장 함수입니다. any 및 all은 특정 조건이 데이터세트 또는 데이터세트의 하위 집합에서 충족되는지 확인하는 데 유용할 수 있습니다. 예를 들어 열의 값이 누락되었는지 또는 열의 모든 값이 특정 범위 내에 있는지 확인하는 데 사용할 수 있습니다.

다음은 짝수 값과 모든 홀수 값이 있는지 확인하는 간단한 예시 코드입니다.

data = [1, 3, 5, 7]
print(any(x % 2 == 0 for x in data))
print(all(x % 2 == 1 for x in data))
--------------------------------------
False
True


next

next는 반복자에서 다음 항목을 검색하는 데 사용됩니다. 반복자는 list, tuple, set 또는 dictionary와 같이 반복될 수 있는 객체로 Python특징 중 하나입니다. next는 일반적으로 반복자 또는 생성기 개체를 통해 반복하기 위해 데이터 과학에서 사용됩니다. 이를 통해 사용자는 iterable에서 다음 항목을 검색할 수 있으며 대규모 데이터 세트 또는 스트리밍 데이터를 처리하는 데 유용할 수 있습니다.

아래에서 0과 1 사이의 난수를 산출하는 생성기 random_numbers()를 정의합니다. 그런 다음 next() 함수를 사용하여 생성기에서 0.9보다 큰 첫 번째 숫자를 찾습니다.

import random

def random_numbers():
    while True:
        yield random.random()

# 0.9보다 큰 첫번째 숫자를 찾음
num = next(x for x in random_numbers() if x > 0.9)
print(f"First number greater than 0.9: {num}")
------------------------------------------------------
First number greater than 0.9: 0.9791671465075296


defaultdict

defaultdict는 누락된 키에 대한 기본값을 제공할 수 있는 내장 dict 클래스의 하위 클래스입니다. defaultdict는 희소 행렬이나 feature vector로 작업할 때와 같이 누락되거나 불완전한 데이터를 처리하는 데 유용할 수 있습니다. 범주형 변수의 빈도를 계산하는 데에도 사용할 수 있습니다.

예를 들어 리스트에 있는 항목의 빈도를 계산합니다. int는 누락된 키를 0으로 초기화하는 defaultdict의 기본 팩토리로 사용됩니다.

from collections import defaultdict

count = defaultdict(int)
for item in ['a', 'b', 'a', 'c', 'b', 'a']:
    count[item] += 1

count
---------------------------------
defaultdict(int, {'a': 3, 'b': 2, 'c': 1})


partial

partial은 일부 인수가 미리 채워진 기존 함수에서 새 함수를 생성할 수 있는 functools 모듈의 함수입니다. partial은 특정 매개 변수 또는 인수가 미리 채워진 사용자 지정 함수 또는 데이터 변환을 만드는 데 유용할 수 있습니다. 이렇게 하면 함수를 정의하고 호출할 때 필요한 상용구 코드의 양을 줄이는 데 도움이 될 수 있습니다.

여기서 우리는 partial을 사용하여 값 1로 고정된 인수 중 하나를 사용하여 기존 add 함수에서 새 함수 증분을 만듭니다.
increment(1) 호출은 기본적으로 add(1, 1) 호출입니다.

from functools import partial

def add(x, y):
    return x + y

increment = partial(add, 1)
increment(1)
------------------------------
2




lru_cache

lru_cache는 제한된 크기의 캐시로 함수의 결과를 캐싱할 수 있는 functools 모듈의 데코레이터 함수입니다. lru_cache는 계산 비용이 많이 드는 함수 또는 동일한 인수로 여러 번 호출될 수 있는 모델 훈련 절차를 최적화하는 데 유용할 수 있습니다. 캐싱은 함수 실행 속도를 높이고 전체 계산 비용을 줄이는 데 도움이 될 수 있습니다.

다음은 캐시를 사용하여 피보나치 수를 효율적으로 계산하는 예입니다(컴퓨터 과학에서 메모이제이션이라고 함).

from functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
    if n <= 1:
    return n
    return fibonacci(n - 1) + fibonacci(n - 2)

fibonacci(1e3)
----------------------------------------------
4.346655768693743e+208


Dataclasses

@dataclass 데코레이터는 정의된 속성을 기반으로 __init__, __repr__ 및 __eq__와 같은 클래스에 대한 몇 가지 특수 메서드를 자동으로 생성합니다. 이렇게 하면 클래스를 정의할 때 필요한 상용구 코드의 양을 줄이는 데 도움이 될 수 있습니다. 데이터 클래스 객체는 무엇보다도 데이터 포인트, 특징 벡터 또는 모델 매개변수를 나타낼 수 있습니다.

이 예에서 dataclass는 name, age 및 city의 세 가지 속성이 있는 간단한 클래스 Person을 정의하는 데 사용됩니다.

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int
    city: str

p = Person("Lee", 30, "Seoul")
print(p)
------------------------------------------
Person(name='Lee', age=30, city='Seoul')

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다