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>
enumeratorfor 루프를 사용해서 전체 튜플 리스트에서 원소를 뽑아내서 출력해보자.
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