4. 데이터 고급 처리 Last updated: 2023-10-17 10:29:16

파이썬은 데이터를 분석하는데 좀더 편리한 기능들을 제공한다. 파이썬에서 제공하는 특별한 데이터 고급 처리 방식들을 익혀 사용하면 보다 간결하고 효율적인 코딩을 작성할 수 있을 것이다.

4.1 컴프리헨션 (comprehension)

컴프리헨션(comprehension)은 파이썬에서 리스트, 세트, 딕셔너리 등 집합 데이터를 조건문을 활용해 한줄에 생성할 수 있도록 제공하는 진화된 집합 데이터 생성 방식이다. 컴프리헨션 구문 안에서는 for 반복문이 사용되고, 반복할 대상 혹은 방법이 기술된다. 필요한 경우 if 조건문을 추가해 대상을 선별하고, 최종 결과에 값을 더하거나 곱하는 연산을 통해 최종 결과로 리스트, 세트, 딕셔너리 등의 값을 생성한다.



4.1.1 홀수 리스트 생성하기

다음은 for 문을 이용해 홀수에 대한 리스트 변수를 생성하는 일반적인 방법이다.

[예제 3-157] mod 연산으로 홀수 출력하기

# [1] 후보 숫자 리스트
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
odd_numbers = []

# [2] 후보 숫자들에 대해 for 반복문 실행
for x in numbers:
    # [3] mod 연산을 통해 나머지가 1인지 검사
    if (x % 2) == 1:
        # [4] 홀수 값을 odd_numbers 리스트에 추가
        odd_numbers.append(x)

print(odd_numbers)

[결과]

[1, 3, 5, 7, 9]

다음은 위와 동일한 기능을 컴프리헨션을 이용해 구현하는 코드이다. 위의 방법과 결과가 같지만 위에서 [2] ~[4]의 코드를 컴프리헨션에서는 한 줄에 구현하였다.

형식

new_list = [expresion for item in iterable if condition == True]

파라미터

• iterable : 반복자, for 반복의 대상이 되는 집합 개체 등
• condition : 조건식으로 True 혹은 False의 결과 생성 조건
• item (object) : 반복되는 항목

[예제 3-158] 컴프리헨션으로 리스트에서 홀수 리스트 구하기

# [1] 후보 숫자 리스트
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

odd_numbers = [x for x in numbers if (x % 2) == 1]
print(odd_numbers)

[결과]

[1, 3, 5, 7, 9]

후보 숫자들에 대해 컴퓨리헨션을 통해 for 반복문 실행후 mod 연산을 통해 나머지가 1인지 검사하여 리스트로 만들어서 odd_numbers 변수에 할당한다.



4.2 반복자 (iterator)

iterator는 반복 가능한 객체로 값을 차례로 꺼낼 수 있다. 반복 가능(iteratable)한 객체는 iter( ) 메서드를 이용해 iterator 객체를 만들 수 있다. iterator 객체가 만들어지면 순차적으로 항목을 한 개 씩 가져오는 next( ) 메서드를 사용할 수 있다. iterator를 for 문의 반복자로 사용하면 next( ) 함수를 이용해 항목을 한 개 씩 꺼내어 사용하게 한다.

형식

iter_items = iter(collect_var)
item = next(iter_items)
item = next(iter_items)

파라미터

• collect_var : 반복자인 iterator 생성이 가능한 list, tuple과 같은 집합 객체 변수
• iter_items : 반복자 객체
• item : 반복자에서 현재 순서에 따라 꺼내온 각 집합 객체의 각 항목

우선 리스트 변수를 iterator로 변환해 next( ) 메서드를 이용해 항목을 한 개 씩 출력해 본다.


[예제 3-159] 반복자의 next( ) 함수 사용하기

# 리스트 변수 생성
idx = [1,2,3,4,5]

# iterator 객체로 변환
idx_iter = iter(idx)
print("idx_iter's type :", type(idx_iter))

# next() 함수로 항목을 한개씩 출력
print(next(idx_iter))
print(next(idx_iter))
print(next(idx_iter))
print(next(idx_iter))
print(next(idx_iter))

[결과]

idx_iter's type : <class 'list_iterator'>
1
2
3
4
5

리스트를 iter( ) 메서드로 반복자를 만들고 next( )함수를 통해 값을 하나씩 얻어온다.


iterator를 생성해서 for 문의 반복자로 사용해 보자.

[예제 3-160] 리스트 반복자로 for문 반복하기

# 리스트 변수 생성
idx = [1,2,3,4,5]

# iterator 객체로 변환
for i in iter(idx):
    print(i)

[결과]

1
2
3
4
5

위 예제는 리스트 객체를 iter( ) 함수로 반복자를 만들고 이를 바로 for 문의 반복자로 사용하는 예제이다.


물론 튜플 객체를 iterator로 변환할 수도 있다.


[예제 3-161] 튜플 객체의 반복자 변환하기

# 튜플 변수 생성
fruits = ('apple', 'peach', 'orange')

for f in iter(fruits):
    print(f)

[결과]

apple
peach
orange

튜플도 리스트와 동일하게 반복자로 변환이 가능하다.



4.2.1 세트 객체로 iterator 생성

세트 객체를 iterator로 변환하여 for 반복문에 사용하는 예제를 본다. 세트 객체도 리스트와 사용법은 동일하다.

형식

set_items = {value1, value2, value3}
for item in iter(set_items):
    # do something with item

파라미터

• set_items : 세트 객체
• value1, value2, value3 : 세트를 구성하는 각 항목
• item : 세트에서 iter( ) 함수를 통해 한 개씩 꺼내온 각 항목

[예제 3-162] 세트 변수로 반복자 객체 변환하기

# 세트 변수 생성
fruits = {'apple', 'peach', 'orange', 'apple'}

for f in iter(fruits):
    print(f)

[결과]

peach
orange
apple


4.3 range

range( )는 규칙에 맞는 숫자형 반복자(iterator)를 생성해준다. 파이썬의 for 문은 반복자를 입력으로 사용할 경우 순서대로 한 개씩 반복하여 for 문을 실행할 수 있도록 해준다. 리스트, 튜플, 세트, 딕셔너리, range( ) 등 집합형 데이터를 반복자로 사용할 수 있다. 그 중에서 range( ) 메서드는 숫자형 범위 반복자를 쉽게 만들 수 있는 메서드이다.

형식

range(start, stop, step)
또는
range(stop)

파라미터

• start (int) : 시작 숫자
• stop (int) : 종료 숫자
• step (int) : 증감을 위한 값으로 양수면 증가하고 음수면 감소한다. 기본값은 1이다.

반환

(iterator) 반복 가능한 iterator 개체


A. range로 리스트 생성

range( ) 메서드를 이용해 1~10사이 숫자 반복자를 생성하여 for 문 반복문에 활용해 홀수 숫자 리스트를 얻어올 수 있다.

[예제 3-163] range, comprehension, if 이용해 0~9 사이 홀수 숫자 얻어오기

odd_numbers = [x for x in range(1, 10) if (x % 2) == 1]
print(odd_numbers)

[결과]

[1, 3, 5, 7, 9]

range( ) 메서드의 step을 활용하면 if 문을 사용하지 않고도 홀수 숫자 리스트를 얻어올 수 있다.


[예제 3-164] range, comprehension 이용해 0~9 사이 홀수 숫자 얻어오기

odd_numbers = [x for x in range(1, 10, 2)]
print(odd_numbers)

[결과]

[1, 3, 5, 7, 9]

range( ) 메서드의 step을 활용한 결과를 리스트로 형변환하면 컴프리헨션을 사용하지 않아도 홀 수 숫자를 얻어올 수 있다.


[예제 3-165] range( ) 메서드로 홀수 목록 얻어오기

odd_numbers = list(range(1, 10, 2))
print(odd_numbers)

[결과]

[1, 3, 5, 7, 9]

다음은 range( ) 메서드를 이용해 짝수 숫자 리스트 구하기 예제이다.


[예제 3-166] range( ) 메서드로 짝수 목록 얻어오기

odd_numbers = list(range(2, 11, 2))
print(odd_numbers)

[결과]

[2, 4, 6, 8, 10]


4.4 enumerate

enumerate는 for 반복문에서 값 목록으로 반복문을 실행할 때 index를 만들어주는 방법이다. 값으로만 구성된 집합형 데이터 앞에 숫자형 index를 추가해서 반환해 준다. 단, enumerate 메서드를 사용해 index와 값이 반환될 때 순서는 index가 먼저, 그리고 값이 나중이다.

형식

for idx, item in enumerate(collect_var):
    # do something with idx, item

파라미터

• collect_var (object) : 리스트, 튜플, 세트와 같은 집합 객체
• idx (int) : 0 부터 증가되는 인덱스 숫자
• item (object) : 집합 객체에서 꺼내온 각 항목

A. enumerate를 이용한 for 반복문

enumerate를 for 문에서 사용하는 방법에 대해 예제를 통해 알아보자.

[예제 3-167] enumerate( ) 이용하여 for 문 반복하기

# 리스트 변수 생성
fruits = ['apple', 'peach', 'orange', 'apple']

print("# Only item value")
# 리스트를 for 문의 반복자로 사용
for item in fruits:
    # 반환된 값을 출력
    print('\t', item)
    
print("# item value with index")
# enumerate를 이용해 값과 함께 index도 얻어온다.
for idx, item in enumerate(fruits):
    # 반환된 index와 값을 출력
    print('\t', idx, item)

[결과]

# Only item value
        apple
        peach
        orange
        apple
# item value with index
        0 apple
        1 peach
        2 orange
        3 apple

enumerate( ) 함수를 이용하면 목록형 집합 데이터에서 값을 얻어올 때 0부터 시작하는 인덱스를 함께 얻어옵니다. 인덱스 값을 사용하려면 enumerate( ) 함수를 사용하면 된다.

다음은 range를 iterator로 사용하고 enumerate를 이용해 index를 받아오는 예제이다.


[예제 3-168] range( )와 enumerate( ) 함수 동시 사용하기

for idx, item in enumerate(range(10, 20, 2)):
    print('\t', idx, item)

[결과]

        0 10
        1 12
        2 14
    	3 16
    	4 18

range( ) 함수로 만든 숫자 목록과 enumerate( ) 함수로 얻어온 인덱스를 함께 사용할 수 있다.



4.5 zip

zip은 두 개 이상의 집합 객체를 짝을 이루어 한 쌍을 하나씩 반환하도록 반복 리스트를 만들어주는 메서드이다. 만일 두 개의 리스트가 있다고 가정한다. 하나는 과일 이름들이 들어있고, 다른 하나에는 각 과일의 갯수가 들어 있다. 이 두 리스트를 이용해 for 반복문을 실행하는데 한번에 과일 이름과 갯수가 같이 필요하다.

형식

for item_v1, item_v2 in zip(collect_var1, collect_var2):
    # do something with item_v1, item_v2

파라미터

• collect_var1 (object) : 리스트, 튜플, 세트와 같은 집합 객체
• collect_var2 (object) : 리스트, 튜플, 세트와 같은 집합 객체, collect_var1과 collect_var2의 길이가 같아야 한다.
• item_v1 (object) : for 반복문에 따라 collect_var1에서 꺼내온 항목
• item_v2 (object) : for 반복문에 따라 collect_var2에서 꺼내온 항목


A. zip을 이용한 for 문 반복

우선 index를 이용하는 예제를 살펴보자.


[예제 3-169] 집합 객체의 길이로 range( ) 범위값 생성하기

fruit = ['apple', 'peach', 'mango', 'orange', 'grape']

for i in range(len(fruit)):
    print(fruit[i], ":", fruit_cnt[i])

[결과]

apple : 3
peach : 4
mango : 2
orange : 6
grape : 1

위 예제를 zip 메서드를 이용해 다음과 같이 구현할 수 있다.


[예제 3-170] 두개 리스트의 zip을 통한 for문 실행하기

fruit = ['apple', 'peach', 'mango', 'orange', 'grape']
fruit_cnt = [3, 4, 2, 6, 1]

for name, count in zip(fruit, fruit_cnt):
    print(name, ":", count)

[결과]

apple : 3
peach : 4
mango : 2
orange : 6
grape : 1

두 개의 fruit과 fruit 리스트 객체를 zip을 통해 짝을 이뤄 반환되도록 하여 for 문을 반복하여 실행시킨다. zip( ) 함수를 사용할 때 주의할 점은 입력 리스트의 길이가 서로 같아야 한다.



B. enumerate와 zip 함께 사용

enumerate와 zip을 함께 사용할 수도 있다.

형식

for index, item in enumerate(zip(collect_var1, collect_var2)):
    # do something with index, item

파라미터

• collect_var1 (object) : 리스트, 튜플, 세트와 같은 집합 객체
• collect_var2 (object) : 리스트, 튜플, 세트와 같은 집합 객체, collect_var1과 collect_var2의 길이가 같아야 한다.
• index (int) : for문 반복에 따라 0부터 증가 되는 인덱스 숫자
• item (object) : for 반복문에 따라 collect_var1, collect_var2에서 꺼내온 항목의 튜플, 사용할 때는 item[0], item[1]과 같이 각각 collect_var1와 collect_var2의 항목을 사용할 수 있다.

[예제 3-171] zip과 enumerate를 이용한 for문 실행하기

fruit = ['apple', 'peach', 'mango', 'orange', 'grape']
fruit_cnt = [3, 4, 2, 6, 1]

# enumerate를 이용해 index를 구하고, zip을 이용해 두 리스트의 항목을 순서대로 가져온다.
for idx, item in enumerate(zip(fruit, fruit_cnt)):
    print(f"[{idx}] {item[0]} : {item[1]}")

[결과]

[0] apple : 3
[1] peach : 4
[2] mango : 2
[3] orange : 6
[4] grape : 1

위 예제에서 enumerate를 통해 생성한 인덱스는 idx 변수에 값이 할당되고, zip을 이용해 생성한 fruit과 fruit_cnt의 짝은 item 변수에 튜플 형태로 할당된다.