for
루프for
루프를 사용할 수 있는 임의 객체를 반복가능한 객체(iterable objects) / 이터러블즈(iterables)라고 부른다. next()
함수를 사용해서 객체 내부에 포함된 임의 값을 차례로 끄집어 낼 수 있고 마지막에 StopIteration
을 반환시킨다. iterable
에는 리스트(list), 문자열(string), 튜플(tuple), 집합(set), 딕셔너리(dictionary) 등이 포함되고 iter()
를 적용시커 반복자(iterator
)를 생성시킨다. 대표적인 파이썬 반복자에는 다음이 포함된다.
[]
()
{}
{ : }
자료형이 반복자인지 판별하는 함수가 next()
다. 반복자 객체를 next()
함수로 돌리게 되면 마지막에 StopIteration
을 반환시키게 된다. 리스트 객체를 반복해서 원소를 뽑아내고 관련 연산작업을 수행할 경우 for
루프를 동원해야 한다. 하지만, enumerate()
함수로 반복자 객체로 변환시키게 되면 next()
를 사용해서 작업하는 것이 가능하다.
리스트 for
루프
회귀분석
기계학습
리스트 반복자(iterables)
for
루프를 돌리게 되면 enumerator
객체는 앞에 index
가 붙게 된다.
(0, '회귀분석')
(1, '기계학습')
리스트 반복자 - next()
(0, '회귀분석')
(1, '기계학습')
Error in py_call_impl(callable, dots$args, dots$keywords): StopIteration:
Detailed traceback:
File "<string>", line 1, in <module>
enumerator
for
루프를 사용해서 전체 튜플 리스트에서 원소를 뽑아내서 출력해보자.
packages = ["dplyr", "ggplot", "broom"]
features = ["데이터 조작", "시각화", "모형"]
toolchain = zip(packages, features)
for package, feature in toolchain:
print(f"{package} --> {feature}")
dplyr --> 데이터 조작
ggplot --> 시각화
broom --> 모형
for
루프를 사용해서 전체 튜플 리스트를 뽑아낼 때 조금 아쉬운 점은 위치 index
에 대한 것도 함께 알았으면 좋겠다는 생각이 들 것이다. 이런 부족한 점을 충족시켜 주는 것이 enumerate
가 짜짠… 역할을 수행하게 된다. enumerate
함수는 순서가 있는 자료형(리스트, 튜플, 문자열)을 입력받아 색인 index
을 해당 원소값에 포함시키는 역할을 수행한다.
먼저 enumerate()
함수로 객체를 생성하고 index
와 item
을 추출하고 튜플 item
에서 각 튜플 원소를 package
와 feature
로 추출시킨다. 이를 통해서 index
, package
, feature
를 튜플에서 enumerate
를 통해서 뽑아낼 수 있게 된다.
toolchain = zip(packages, features)
for index, item in enumerate(toolchain):
package, feature = item
print(f"순서 {index}:, 팩키지 {package}, --> {feature}")
순서 0:, 팩키지 dplyr, --> 데이터 조작
순서 1:, 팩키지 ggplot, --> 시각화
순서 2:, 팩키지 broom, --> 모형
for
루프for
루프 - 문자열“데이터 사이언스” 문자열을 for
루프를 사용해서 각 문자를 추출해낼 수 있다.
Data Science: 데
Data Science: 이
Data Science: 터
Data Science:
Data Science: 사
Data Science: 이
Data Science: 언
Data Science: 스
for
루프 - 리스트파이썬에서 가장 일반적인 자료구조인 리스트(list
)에 대한 반복자(iterator
)로 for
루프를 사용해보자.
데이터 사이언스 언어: R
데이터 사이언스 언어: 파이썬
데이터 사이언스 언어: C/C++
enumerate()
를 사용하게 되면 index
를 얻게 되어 앞서 for
문에 리스트를 사용할 때에 비해 도움이 되는 경우가 많다. print(list(enumerate(models)))
을 출력시켜 보면 기존 리스트(models
)에 index
가 붙은 튜플 리스트를 확인할 수 있다.
[(0, '회귀분석'), (1, '기계학습'), (2, '딥러닝')]
- 데이터 사이언스 모형 1: 회귀분석
- 데이터 사이언스 모형 2: 기계학습
- 데이터 사이언스 모형 3: 딥러닝
zip()
을 사용하게 되면 리스트와 리스트를 결합할 때 유용하다.
languages = ["R", "파이썬", "텐서플로우"]
models = ["회귀분석", "기계학습", "딥러닝"]
for language, model in zip(languages, models):
print(f"데이터 사이언스 언어: {language}, 모형: {model}")
데이터 사이언스 언어: R, 모형: 회귀분석
데이터 사이언스 언어: 파이썬, 모형: 기계학습
데이터 사이언스 언어: 텐서플로우, 모형: 딥러닝
특히 *
을 사용하면 압축(zip
)한 것을 unzip
하여 풀 수 있다.
('R', '회귀분석') ('파이썬', '기계학습') ('텐서플로우', '딥러닝')
for
루프 - 튜플리스트와 마찬가지로 튜플도 for
루프를 사용해서 반복하여 원소를 끄집어 낼 수 있다.
데이터 사이언스 언어: R
데이터 사이언스 언어: 파이썬
데이터 사이언스 언어: C/C++
for
루프 - 집합(set)리스트, 튜플과 마찬가지로 집합(set)도 for
루프를 사용해서 반복하여 원소를 끄집어 낼 수 있다.
데이터 사이언스 언어: 파이썬
데이터 사이언스 언어: R
데이터 사이언스 언어: C/C++
for
루프 - 딕셔너리딕셔너리(dictionary)는 키-값(key-value)를 갖는 자료형이다. 딕셔너리의 경우 .items()
, .keys()
, .values()
메쏘드를 사용해서 다양한 작업을 수행할 수 있다. 딕셔너리에 .items()
를 for
문과 결합하여 사용한다.
입력사례
data_science = {"R": "젠틀맨, 이하카",
"파이썬": "귀도 반 로섬",
"C/C++": "톰슨, 리치"}
for item in data_science.items():
print(item)
('R', '젠틀맨, 이하카')
('파이썬', '귀도 반 로섬')
('C/C++', '톰슨, 리치')
키-값 딕셔너리
for language, creator in data_science.items():
print(f"- 데이터 사이언스 언어: {language}, \n ㄴ 창시자: {creator}")
- 데이터 사이언스 언어: R,
ㄴ 창시자: 젠틀맨, 이하카
- 데이터 사이언스 언어: 파이썬,
ㄴ 창시자: 귀도 반 로섬
- 데이터 사이언스 언어: C/C++,
ㄴ 창시자: 톰슨, 리치
for
루프 → while
루프반복자(iterables) 객체는 모든 내부 원소를 전부 거치게 되면 expendable
이라 next()
를 돌릴 때마다 하나씩 소모되어 모두 소진되게 되면 동시에 StopIteration
오류가 생성된다. 이런 특성을 이용하여 자동으로 while
루프를 빠져나오게 된다. 즉, while
문 내부에 try
- except
- break
를 구성할 수 있다.
for
루프 - 리스트
데이터 사이언스 언어: R
데이터 사이언스 언어: 파이썬
데이터 사이언스 언어: C/C++
while
루프 - 반복자
languages_iter = iter(languages)
while True:
try:
language = next(languages_iter)
print(f"데이터 사이언스 언어: {language}")
except StopIteration:
break
데이터 사이언스 언어: R
데이터 사이언스 언어: 파이썬
데이터 사이언스 언어: C/C++
반복자(iterator)에는 enumerate()
, finditer()
등이 포함된다. 정규표현식을 작성해서 다양한 형태로 패턴으로 매치된 결과를 반환시킬 수 있는데 .finditer()
메쏘드를 사용하게 되면 반복자 객체로 매칭결과를 출력시킬 수 있다. 반복가능한 객체가 포함하는 match
객체로 .group()
, .start()
, .end()
, .span()
메쏘드를 각각 적용시킬 수 있다.
import re
sample_text = ''' From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008
Return-Path: <postmaster@collab.sakaiproject.org>
Received: from murder (mail.umich.edu [141.211.14.90]) by frankenstein.mail.umich.edu (Cyrus v2.3.8) with LMTPA;
Received: from prod.collab.uhi.ac.uk ([194.35.219.182])
by paploo.uhi.ac.uk (JAMES SMTP Server 2.1.3) with SMTP ID 899
for <source@collab.sakaiproject.org>;
Sat, 5 Jan 2008 14:09:50 +0000 (GMT)
Received: from nakamura.uits.iupui.edu (nakamura.uits.iupui.edu [134.68.220.122])
by shmi.uhi.ac.uk (Postfix) with ESMTP id A215243002
for <source@collab.sakaiproject.org>; Sat, 5 Jan 2008 14:13:33 +0000 (GMT)
To: source@collab.sakaiproject.org
From: stephen.marquard@uct.ac.za
'''
pattern = re.compile(r'[\w\.]+@[a-z]+\.[a-z]+')
emails = re.finditer(pattern, sample_text)
for email in emails:
print(email)
# iterator는 expendable하기 때문에 다시 재충전
<_sre.SRE_Match object; span=(6, 29), match='stephen.marquard@uct.ac'>
<_sre.SRE_Match object; span=(72, 102), match='postmaster@collab.sakaiproject'>
<_sre.SRE_Match object; span=(365, 391), match='source@collab.sakaiproject'>
<_sre.SRE_Match object; span=(587, 613), match='source@collab.sakaiproject'>
<_sre.SRE_Match object; span=(662, 688), match='source@collab.sakaiproject'>
<_sre.SRE_Match object; span=(699, 722), match='stephen.marquard@uct.ac'>
stephen.marquard@uct.ac
postmaster@collab.sakaiproject
source@collab.sakaiproject
source@collab.sakaiproject
source@collab.sakaiproject
stephen.marquard@uct.ac
딕셔너리로부터 데이터프레임을 생성시키는데 행이름을 index
로 지정하여 만든다.
import pandas as pd
input_dict = {"키" : [160, 170, 180],
"체중" : [70, 55, 100]}
bmi = pd.DataFrame(input_dict, index=['홍길동', '허균', '박제가'])
print(bmi)
키 체중
홍길동 160 70
허균 170 55
박제가 180 100
.iterrows()
데이터프레임에 iterrows()
메쏘드를 적용시킬 경우 생성자(generator) 객체로 변환된다.
<generator object DataFrame.iterrows at 0x11e4deca8>
.iterrows()
생성자
for
루프로 각 원소를 뽑아내게 되면 결과 다음과 같다. 열이 아닌 행기준으로 뽑아낼 수 있다.
('홍길동', 키 160
체중 70
Name: 홍길동, dtype: int64)
('허균', 키 170
체중 55
Name: 허균, dtype: int64)
('박제가', 키 180
체중 100
Name: 박제가, dtype: int64)
.iterrows()
인덱스와 씨리즈
각 행별로 행이름을 기준으로 칼럼을 구성하는 각 요소별로 추출된 씨리즈로 추출된다.
item
&rar;; (인덱스명, 씨리즈)인덱스: 홍길동, 씨리즈: 키 160
체중 70
Name: 홍길동, dtype: int64
인덱스: 허균, 씨리즈: 키 170
체중 55
Name: 허균, dtype: int64
인덱스: 박제가, 씨리즈: 키 180
체중 100
Name: 박제가, dtype: int64
.iteritems()
데이터프레임에 iteritems()
메쏘드를 적용시킬 경우 동일하게 생성자(generator) 객체가 변환된다.
<generator object DataFrame.iteritems at 0x11e5172b0>
.iteritems()
생성자
for
루프로 각 원소를 뽑아내게 되면 결과 다음과 같다. 행이 아닌 열을 뽑아낼 수 있다.
('키', 홍길동 160
허균 170
박제가 180
Name: 키, dtype: int64)
('체중', 홍길동 70
허균 55
박제가 100
Name: 체중, dtype: int64)
.iteritems()
칼럼명과 씨리즈
각 칼럼별로 칼럼명과 씨리즈로 추출할 수 있다.
item
&rar;; (칼럼명, 씨리즈)칼럼명: 키, 씨리즈: 홍길동 160
허균 170
박제가 180
Name: 키, dtype: int64
칼럼명: 체중, 씨리즈: 홍길동 70
허균 55
박제가 100
Name: 체중, dtype: int64
포켓몬과 마블 캐릭터를 대상으로 데이터프레임을 작성해본다.
input_dict = {"포켓몬" : ['피카츄', '피카츄', '이상해씨', '리자몽', '거북왕'],
"마블" : ['아이언맨', '아이언맨', '아이언맨', '스파이더맨', '헐크']}
df = pd.DataFrame(input_dict, index=['1번', '2번', '3번', '4번', '5번'])
print(df)
포켓몬 마블
1번 피카츄 아이언맨
2번 피카츄 아이언맨
3번 이상해씨 아이언맨
4번 리자몽 스파이더맨
5번 거북왕 헐크
칼럼별로 각 캐릭터 빈도수를 산출해본다.
column_cnt = dict()
for column, series in df.iteritems():
values = list(series)
category_cnt = dict()
for category in set(values):
category_cnt[category] = values.count(category)
column_cnt[column] = category_cnt
print(column_cnt)
{'포켓몬': {'리자몽': 1, '이상해씨': 1, '거북왕': 1, '피카츄': 2}, '마블': {'아이언맨': 3, '스파이더맨': 1, '헐크': 1}}
여기서, 칼럼 즉 씨리즈에 포함된 마블 캐릭터명을 셀 경우 리스트 .count()
메쏘드를 사용한다. 이를 위해서 간략한 코드로 확인하면 다음과 같다.
3