일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 재현율
- NVL
- recall
- 오차 행렬
- nvl2
- Batch Normalization
- 강화학습
- DecisionTree
- CASE WHEN
- layer normalization
- LAG
- 정밀도
- 데이터 전처리
- NULLIF
- 비지도학습
- Normalization
- 백엔드
- sorted
- 데이터 프로젝트
- ifnull
- 평가 지표
- 웹서비스 기획
- beautifulsoup
- 감정은 습관이다
- SQL
- 결정트리
- 빠르게 실패하기
- 데이터 분석
- 지도학습
- five lines challenge
- Today
- Total
Day to_day
계속 헷갈려하던 map과 filter함수 개념 및 활용 본문
자바스크립트로 먼저 filter와 map에 대해서 배우면서 개념에 대해서 얼추 감을 잡긴 했지만 항상 헷갈려했었다.
이번에 파이썬으로 다시 배워보면서 개념과 활용까지 확실하게 잡고 갈 예정
def get_eng_title(row):
split = row.split(',')
return split[1]
eng_titles = [get_get_title(row) for row in movies]
위와 같은 예시가 있다고 보자. get_eng_title은 콤마를 기준으로 row를 나누어 row의 인덱스 1을 리턴하는 함수이다.
list comprehension으로 movies에 들어있는 row를 for문을 통해서 하나씩 가져오고, 아까 선언한 get_eng_title 함수에 하나씩 넣는 것이다.
그리고 나온 리턴 값을 다시 리스트로 만들었다.
for문은 하나씩 꺼내와서 함수에 차근차근 넣는 식으로 되어있기 때문에 만약 데이터가 클 경우 이런식으로 사용하면 시간이 너무 오래 걸릴 수가 있다.
map()
map(함수, 리스트)
map의 인자는 함수와 리스트가 들어간다.
map(f(x), list) 이런식으로 주어질때 list = [x,y,z]는 list = [f(x), f(y), f(z)] 즉 함수의 리턴 값으로 모두 반환이된다.
예시
movies = ['Harry Poter', 'Kings man', 'Tall girl']
get_title = lambda row: row.split()[1]
titles = map(get_title, movies)
모든 리스트 요소에 한꺼번에 적용이 되게 하기 위해서 map을 이용한다.
lambda 함수를 사용해서 row를 공백을 기준으로 split하고 그것의 인덱스 1의 요소를 가져와 다시 리스트를 만드는 과정이다. 위의 예시와 비교해 보면 훨씬 더 짧게 코드가 작성된 것을 알 수 있다.
하지만 여기서 print(titles)를 직접하면,
이러한 결과를 얻게된다. 사실 map함수의 결과는 list처럼 보이지만 사실 map이라는 타입을 가진다. 그래서 list로 감싸주지 않고 그냥 출력을 하게되면 위와같은 결과를 얻게되는 것이다.
그렇다면 왜 처음부터 list로 저장을 하지 않는 걸까?
→ 사용자가 원하는 원소를 부를때 그때 함수를 적용해서 반환한다.
만약 10만개의 리스트가 있다면 이것을 모두 함수에 넣어서 다 바꿔놔야하니까 효율적으로 사용하는것!
map으로 약속만 해놓고 사용한 원소에 대해서만 함수로 바꿔서 보내준다.
그래서 print(list(titles))로 출력을 원할 때 '아~ 이 사용자가 모든 결과물을 리스트로 보길 원하는 구나!' 하고 map함수를 그때 적용 시키는 것!
map 함수 활용
# CSV 모듈을 임포트
import csv
def get_titles(books_csv):
with open(books_csv) as books:
reader = csv.reader(books, delimiter=',')
get_title = lambda row: row[0]
titles = map(get_title, reader)
return list(titles)
#list로 감싸지 않고 map 자체로 리턴하면 연산이 되지 않은채로 파일이 닫히게 된다.
#그러면 map을 적용할 수 없으니 list로 감싸서 리턴
books = 'books.csv'
titles = get_titles(books)
for title in titles:
print(title)
books_csv 파일을 열어주고 csv.reader를 통해서 읽는다.
익명 함수 lambda로 제목 부분만 얻고싶기 때문에 row[0]을 리턴하게둔다.
map으로 감싸서 함수(get_title)과 reader 리스트를 가지고 온다.
map함수를 사용하지 않으면 아래와 같은 for문을 이용해서 title list를 새롭게 만들었어야 했을 것이다.
title = []
for row in reader:
titles.append(get_title(row))
return list(titles)
한가지 또 봐야할 것은 list로 감싸지 않고 map 자체로 리턴하면 연산이 되지 않은채로 파일이 닫히게 된다.
그러면 map을 적용할 수 없으니 list로 감싸서 리턴한다.
filter()
다음은 filter 함수!
filter(함수, 리스트)
map함수와 같이 들어가는 인자는 같다.
근데 map에선 list = [f(x), f(y), f(z)] 로 나왔다면
filter는 함수를 적용했을때 내용이 True 라면 그 값을 반환한다.
그래서 만약 f(x)와 f(z)가 참이 나오고 f(y)가 거짓이 나왔다면 x와 z만 반환해주는 것
list = [x,z] 이렇게 말이다.
r_word = filter(starts_with_r, words)
print(r_word)
r로 시작하는 단어만 모두 리스트에 넣어서 print하고 싶을 때, filter함수를 사용할 수 있다.
하지만 위의 예시도 map 함수랑 비슷하게 아래와 같이 뜬다.
filter도 filter 타입을 갖고, 결과를 모두 보고 싶으면 list로 감싸서 print해줘야한다.
filter 함수 활용
def get_titles_of_long_books(books_csv):
with open(books_csv) as books:
reader = csv.reader(books, delimiter=',')
# 함수를 완성하세요.
is_long = lambda row: int(row[3]) > 250
get_title = lambda row: row[0]
long_books = filter(is_long, reader)
long_book_titles = map(get_title, long_books)
return list(long_book_titles)
is_long은 true or false가 나오게 하는 함수이고 get_title은 모든 리스트에 적용해줄 함수이다.
그래서 is_long에는 페이지가 250이상 이라는 조건을 넣어주고 true로 나온 그 값에서 첫번째 원소인 제목만 list에 넣어서 리턴해준다.
여기서 filter에서 map으로 넘어갈때 따로 list로 묶어서 보내줄 필요는 없다.
'Python' 카테고리의 다른 글
[Data Structure] Stack(스택)과 Queue(큐) 비교하기! (1) | 2023.01.19 |
---|---|
Object-Oriented Programming (OOP) (0) | 2023.01.17 |
[정렬하기] sort와 sorted 차이와 활용 (0) | 2022.09.15 |