데이터 분석가:Applied Data Analytics/파이썬

리스트, 딕셔너리, 컴프리헨션

데이터분석 2025. 1. 22. 15:25
320x100
728x90

리스트, 딕셔너리, 컴프리헨션이 들어간 짧은 이야기

옛날 옛적, 마법과 기술이 공존하는 세계가 있었다. 
이곳에는 데이터를 다루는 데 특별한 재능을 가진 젊은 마법사, 파이(Pi)가 살고 있었다. 파이는 마법으로 살아있는 데이터를 창조할 수 있었는데, 그 중 가장 흥미로운 발명품은 데이터 골렘이었다.

데이터 골렘의 제작
파이는 데이터를 정리하고 분석하는 데 골머리를 앓고 있던 날, 새로운 골렘을 만들기 위해 준비를 시작했다. 
먼저 마법 리스트를 사용해 골렘의 재료를 정리했다.
재료 = ["지능", "속도", "호기심", "창의성"]
이 리스트를 기반으로 파이는 딕셔너리로 골렘의 특성을 설계했다.

결과적으로, 골렘의 특성은 다음과 같았다:

골렘의 학습
골렘이 더 효율적으로 데이터를 다룰 수 있도록, 파이는 골렘에게 데이터 패턴을 학습시키는 훈련을 시작했다. 파이는 1부터 10까지의 숫자 중 짝수와 홀수를 구별하는 컴프리헨션 마법을 가르쳤다.

골렘은 이 마법을 배운 뒤, 즉시 데이터를 분류하고 정리하는 능력을 갖추게 되었다.

예기치 못한 일
하지만 문제가 생겼다. 골렘이 너무 호기심이 많아져, 스스로 데이터를 생성하기 시작한 것이다. 이 데이터를 관리하기 위해 파이는 또 다른 컴프리헨션 마법을 사용했다.

생성된 데이터를 기반으로
결국, 골렘은 스스로 학습하고 데이터를 정리하며, 마을의 모든 데이터를 관리하는 훌륭한 데이터 분석가가 되었다.

 

다차원 리스트

1차원 리스트 :
list_o = ['a', 'i', 'f', 'f', 'e', 'l']
list_o

2차원 리스트 : 행의 길이가 3인 리스트 
list_tw = [[1, 2], ['ㄱ', 'ㄴ'], ['a', 'b']]
list_tw

 

2차원 리스트의 인덱싱
3행 1열 출력 : list_tw[2][0]

 

3차원 리스트
list_th = [[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]],\ [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]] list_th
이를 쉽게 설명하면 다음과 같다.

이 코드에서 **list_th**는 상자 여러 개를 담고 있는 큰 상자라고 생각하면.

이 큰 상자 안에는 두 개의 작은 상자가 들어 있고.

  1. 첫 번째 작은 상자는 숫자들로 이루어진 상자.
    • 이 안에는 또 다른 상자들이 있어, 각각 3개의 숫자를 담고 있으며
    • 예를 들어, 첫 번째 상자에는 [1, 2, 3], 두 번째 상자에는 [4, 5, 6] 같은...
  2. 두 번째 작은 상자는 글자들(알파벳)로 이루어진 상자.
    • 이 안에도 또 다른 상자들이 있고, 각각 3개의 글자를 담고 있으며,
    • 예를 들어, 첫 번째 상자에는 ['a', 'b', 'c'], 두 번째 상자에는 ['d', 'e', 'f']가 있다

이런 상자를 리스트라고 불르며,  list_th는 숫자와 글자를 정리해둔 "상자들"을 모아둔 큰 상자이다,

 

3차원일때는 [depth][행][열]로 적고 이를 통해 인덱싱할 수 있다. (3차원의 리스트의 길이는? 2개 즉, 큰상자 두개가 리스트의 길이이며 depth 이다)

C를 인덱싱 한다면

depth 2, 1행, 3열
list_th[1][0][2] 이렇게 된다.

 

리스트 함수

 age = [60, 28, 30, 34, 66, 11] 이 리스트에서 최댓값과 최솟값을 구하는 함수 :  max()min()
이며 max(age) 는 66이 됩니다. 이것은 int형과 str형은 서로 크고 작음을 비교할 수 없기때문에 사용할 수 없다.
 
아스키 코드 ➔ 문자열로 변화하는 함수는 chr()이고, 문자열 ➔ 아스키 코드로 변환하는 함수는 ord()

문자열을 아스키 코드로 ; ord('m'), ord('크'), ord('O'), ord('A')
결과 ; 

(109, 53356, 79, 65)

 

※ 참고로 아스키코드로 바꿨을때 영문자 보다 한글자가 아스키코드숫자가 더 크다.

 

sum()

인자로 들어온 리스트나 튜플의 숫자형 자료형들을 모두 더하는 함수

상위의 age를 sum(age) 결과는 229

 

enumerate() 

enumerate() 함수는 리스트의 원소에 순서값을 부여 for문과 같이 사용

napoli_player = ['minjae', '크바라츠헬리아', 'Osimhen', 'Anguissa']
for i in enumerate(napoli_player):
    print(i)

결과 값은

(0, 'minjae')
(1, '크바라츠헬리아')
(2, 'Osimhen')
(3, 'Anguissa')

 

zip() 

zip() 함수는 여러 개의 순회 가능한(iterable) 객체를 인자로 받고, 각 객체가 담고 있는 원소를 순차적으로 접근할 수 있는 반복자(iterator)를 반환. 이 때 반복자, 즉 이터레이터는 파이썬에서 반복적으로 요소를 하나씩 꺼내어 처리할 수 있는 객체를 부르는 이름

# for문에 zip을 넣고 출력해보기
napoli_num = [3, 77, 9, 99]
napoli_player = ['minjae', '크바라츠헬리아', 'Osimhen', 'Anguissa']

for i in zip(napoli_num, napoli_player):
    print(i)
(3, 'minjae')
(77, '크바라츠헬리아')
(9, 'Osimhen')
(99, 'Anguissa')

 

묶어둔 데이터를 해제하고 싶으면? zip(*) 을 활용!
위치 인수에서 리스트 앞에 *를 붙이면 언패킹(unpacking)할 수 있었던 것처럼 zip()에서도 *은 동일하게 작용

age = [3, 77, 9, 99]
name = ['minjae', '크바라츠헬리아', 'Osimhen', 'Anguissa']

check_zip = list(zip(age, name))

# zip이 잘 되었는지 확인
print(check_zip)
new_num, new_player = zip(*check_zip) # unzip 활용 해체
print(new_num)
print(new_player)
[(3, 'minjae'), (77, '크바라츠헬리아'), (9, 'Osimhen'), (99, 'Anguissa')]

print(check_zip) 결과

[(3, 'minjae'), (77, '크바라츠헬리아'), (9, 'Osimhen'), (99, 'Anguissa')]
(3, 77, 9, 99)
('minjae', '크바라츠헬리아', 'Osimhen', 'Anguissa')

zip(*check_zip) 한결과 밑에 두줄

 

딕셔너리 함수

key-value 추가하기 : setdefault(), update()

setdefault()

  • 이미 해당 key가 있을 때: 그 key의 value를 반환
  • key가 없을 때: 딕셔너리에 key:value를 저장하고 value를 반환

update()

  • 특정 key-value 조합을 삽입
반복문으로 아스키 코드 확인
for i in ['a', 'b', 'c', 'd']:
    print(ord(i))
97
98
99
100
위에서 알파벳과 아스키 코드로 딕셔너리를 만들면. 딕셔너리의 형태는 {Key1:Value1, Key2:Value2, Key3:Value3, ...}
dict_uni =  {'a': 97, 'b': 98, 'c': 99, 'd': 100}
dict_uni
{'a': 97, 'b': 98, 'c': 99, 'd': 100}
딕셔너리에 이미 있는 key 넣어보기 dict_uni.setdefault('c')
99

setdefault()를 활용해서 'e'를 추가해보기
새로운 key만 넣기
dict_uni.setdefault('e')
dict_uni

{'a': 97, 'b': 98, 'c': 99, 'd': 100, 'e': None}

 

추가도 할 수 있고 수정까지 할 수 있는 함수인 update()

 

setdefault()는 딕셔너리에 키가 없을 경우 기본값을 추가
update()는 딕셔너리에 여러 키-값 쌍을 추가하거나 기존 키의 값을 수정

 

key-value 삭제하기 : pop(), popitem()

pop()

리스트에서 pop() 함수는 마지막 요소를 출력하고 그 이후에 마지막 요소를 삭제

리스트와 다르게 딕셔너리에서는 pop()은 key를 넣어줘야 된다.

popitem()

리스트에서 pop()처럼 딕셔너리에서 특정 key를 지정하지 않아도 마지막 value만 출력해주는 함수

nums = list(range(1, 11)) # [1, 2, ..., 10]

result = 0 # 결과값 - 여기에 숫자를 계속 더해줌

for i in range(10):

result += nums.pop()    # pop()으로 리스트의 마지막 값을 꺼내 더함

print(result) # 55

  1. nums.pop(): nums 상자에서 마지막 숫자를 꺼내서
    예: [1, 2, 3]에서 3을 꺼내오면, 이제 nums는 [1, 2]가 됨.
  2. 꺼낸 숫자를 result에 더해.
    예: result가 10이고, 꺼낸 숫자가 3이면 10 + 3 = 13이 됨.
  3. 즉, 마지막 숫자를 꺼내고, 그걸 result에 계속 더함.

 

fromkeys()

fromkeys()는 리스트나 튜플을 넣으면 자동으로 딕셔너리를 만들 수 있는 함수

 

in / not in

리스트와 딕셔너리에 공통으로 사용할 수 있는 예약어 in / not in

 요소가 들어있는지 확인하는 예약어로 조건문과 자주 쓰이며 요소가 있는지 없는지를 알 수 있다. in / not in 의 리턴값은 bool. 즉 True 또는 False로 리턴

딕셔너리에서 in만으로는 key만 확인이 가능하고 value는 가능하지 않다. value를 확인하기 위해서는 이전에 배웠던 values() 함수와 함께 쓰면 된다.

dict_uni = {'a': 97, 'b':98, 'c':99, 'd':100}
100 in dict_uni.values()
True

 

 

 

※ #1) `dict(키=값, 키=값, 키=값)`
--> key에 작은 따옴표나 큰 따옴표를 할 필요가 없음. 단, key 문자열만 가능
#2) `dict([(키, 값), (키, 값), (키, 값)])`
--> key가 문자열이라면, 따옴표가 필요
#3) `dict({키:값, 키:값, 키:값})`
--> key가 문자열이라면, 따옴표가 필요 (출처 : 모두연 교육 중)

 

컴프리헨션

1. 리스트 컴프리헨션

반복문과 컴프리헨션

# 반복문
list_for = []
for i in range(0, 11, 2):
    list_for.append(i)
print(list_for)                    결과 : [0, 2, 4, 6, 8, 10]
 
# 리스트 컴프리헨션
[x for x in range(0, 11, 2)]   결과 : [0, 2, 4, 6, 8, 10]
출력을 내는 두 코드를 비교해 보면
[같은 출력을 내는 두 코드(반복문과 컴프리헨션)] (이미지 출처 : 모두연 강의 자란다파이썬 김인유강사님)

 

반복문으로 리스트를 만들 때는 반복문을 쓰기 전에 리스트 자체를 만드는 코드를 따로 써줘야 합니다. 즉 리스트명에 비어있는 리스트를 먼저 할당해야 합니다. 반면 컴프리헨션으로 리스트를 만들 때는 가장 바깥에 대괄호   [ ]만 써주면 됩니다
리스트 안에 채우는 내용은 동일하지만 위치가 다릅니다. 반복문은 평소대로 쓰면 되지만 리스트 컴프리헨션은 대괄호 안에 씁니다
반복문 안에서 반복되는 변수의 위치는 상당히 다릅니다. 반복문에서는 콜론(:) 다음 들여쓰기 후에   append()   함수와 그 안에 변수를 썼지만, 컴프리헨션에서는 반복문 앞에 변수만 쓰면 됩니다.

반복문 + 조건문 컴프리헨션

 

# 반복문 + 조건문
list_con = []
for i in range(0, 11):
    if i % 2 == 0:
        list_con.append(i)
print(list_con)                     결과 : [0, 2, 4, 6, 8, 10]
 
# 리스트 컴프리헨션 with 조건문
[x for x in range(1, 11) if x % 2 == 0]      결과 : [2, 4, 6, 8, 10]
조건문을 포함한 두 코드 비교(반복문 + 조건문, 리스트 컴프리헨션 with 조건문)
이 부분은 반복문과 동일하게 시작합니다. 반복문을 사용할 때는 반복문 이전에 리스트명에 비어있는 리스트를 할당합니다. 컴프리헨션은 대괄호를 쓰는 것만으로 리스트를 만들 수 있습니다.
반복문의 위치도 첫번째 예시와 동일
조건문의 위치입니다. 반복문에서는 반복문 콜론(:) 뒤에 조건문을 씁니다. 컴프리헨션에서는 for문 뒤에 조건문이 옵니다. 낯설지만 보다보면 자연스럽게 코드를 읽을 수 있다.
변수의 위치도 반복문에서와 동일
 
# Q. 리스트 컴프리헨션을 사용하여 1 이상 100 이하 홀수들의 합을 계산
total_sum = sum([x for x in range(1, 100)
if x % 2 != 0])
print(total_sum)    결과 : 2500
 
 

중복 표현과 컴프리헨션

# 단짠단짠 조합
sweetie = ['아이스크림', '크림빵', '젤리']
savory = ['감자칩', '팝콘', '뿌셔뿌셔']
[[x, y] for x in sweetie for y in savory]
결과 :
 [['아이스크림', '감자칩'],
 ['아이스크림', '팝콘'],
 ['아이스크림', '뿌셔뿌셔'],
 ['크림빵', '감자칩'],
 ['크림빵', '팝콘'],
 ['크림빵', '뿌셔뿌셔'],
 ['젤리', '감자칩'],
 ['젤리', '팝콘'],
 ['젤리', '뿌셔뿌셔']]
 
위의 코드를 for문으로 표현
sweetie = ['아이스크림', '크림빵', '젤리']
savory = ['감자칩', '팝콘', '뿌셔뿌셔']

sweet_savory = []
for x in sweetie:
    for y in savory:
        sweet_savory.append([x, y])
sweet_savory
결과 :
[['아이스크림', '감자칩'],
 ['아이스크림', '팝콘'],
 ['아이스크림', '뿌셔뿌셔'],
 ['크림빵', '감자칩'],
 ['크림빵', '팝콘'],
 ['크림빵', '뿌셔뿌셔'],
 ['젤리', '감자칩'],
 ['젤리', '팝콘'],
 ['젤리', '뿌셔뿌셔']]
 
# Q. 리스트 컴프리헨션을 사용하여 다음을 출력
# [[1, 11], [2, 22], [3, 33], ..., [9, 99]]

result = [[x, x * 11] for x in range(1, 10)]
print(result)                                           
 
결과 : [[1, 11], [2, 22], [3, 33], [4, 44], [5, 55], [6, 66], [7, 77], [8, 88], [9, 99]]

2. 셋 컴프리헨션 & 딕셔너리 컴프리헨션

셋 컴프리헨션

리스트를 만들 때 쓰는 대괄호 [ ] 대신에 중괄호 { }를 써주면 된다.

{x for x in range(0, 11, 2)}            결과 : {0, 2, 4, 6, 8, 10}

딕셔너리 컴프리헨션

# {나폴리 선수 번호:이름} 딕셔너리
napoli_num = [3, 77, 9, 99]
napoli_player = ['minjae', '크바라츠헬리아', 'Osimhen', 'Anguissa']
{k:v for k, v in zip(napoli_num, napoli_player)}
결과 : {3: 'minjae', 77: '크바라츠헬리아', 9: 'Osimhen', 99: 'Anguissa'}

 

# 딕셔너리 컴프리헨션 with if문
{k:v for k, v in zip(napoli_num, napoli_player) if k < 50}
결과 : {3: 'minjae', 9: 'Osimhen'}
 
test1 = [x**2 for x in range(10)]
print(test1)
결과 : [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
 
실습퀴즈1. 리스트
# list_tw에서 b를 출력해보세요.
list_tw = [[1, 2], ['ㄱ', 'ㄴ'], ['a', 'b']]
print("b는 ", list_tw[2][1])                                    결과 : b는  b
 
실습퀴즈2. 리스트  list_th에서 8과 h를 출력해보세요.  
list_th = [[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]],\
           [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]]

print("8은 ", list_th[0][2][1])
print("h는 ", list_th[1][2][1])                                    결과 : 8은  8      h는  h
 
실습퀴즈3. 아스키 코드
# AIFFEL의 아스키 코드를 알 수 있는 코드를 직접 작성해보세요.
result = ord('A'), ord('I'), ord('f'), ord('e'), ord('l')
result                                                                      결과 : (65, 73, 102, 101, 108)
 
실습퀴즈4. 컴프리헨션
# 1부터 10까지의 숫자 중 홀수인 수를 모은 리스트를 만들어 보세요.
odd_numbers = [x for x in range(1, 10) if x % 2 != 0]
print(odd_numbers)                                                결과 : [1, 3, 5, 7, 9]
 

(출처 : 모두연 강의 자란다파이썬 김인유강사님 중)