15 Tue
TIL
프로그래머스 AI 스쿨 1기
3주차 DAY 2
I. pandas 시작하기
Prerequisite : Table
행과 열을 이용해서 데이터를 저장하고 관리하는 자료구조(컨테이너)
주로 행은 개체, 열은 속성을 나타냄
Pandas 설치하기
pip install pandas
Pandas 시작하기
import pandas
를 통해서 진행 pandas는 관습적으로 pd 축약해서 사용
import pandas as pd
II. pandas로 1차원 데이터 다루기 - Series
Series?
1-D labeled array
인덱스를 지정해줄 수 있음
s = pd.Series([1, 4, 9, 16, 25])
s
0 1
1 4
2 9
3 16
4 25
dtype: int64
t = pd.Series({'one':1, 'two':2, 'three':3, 'four':4, 'five':5})
t
one 1
two 2
three 3
four 4
five 5
dtype: int64
Series + Numpy
Series는 ndarray와 유사하다!
s[1]
4
t[1]
# 딕셔너리도 인덱스로 접근 가능하다
2
t[1:3]
# 슬라이싱도 가능하다
two 2
three 3
dtype: int64
s [s > s.median()]
# 자기 자신의 median(중앙값)보다 큰 값들만 출력
# pandas는 이러한 내장 함수가 존재함
3 16
4 25
dtype: int64
s[[3, 1, 4]]
3 16
1 4
4 25
dtype: int64
import numpy as np
np.exp(s)
0 0.265717
1 2.335211
2 0.802393
3 1.888751
4 0.897110
Name: 임의의 난수, dtype: float64
s.dtype
dtype('int64')
pandas와 numpy의 유사성을 볼 수 있음
Series + dict
series는 dict와 유사하다
t['one']
1
# Series에 값 추가
t['six'] = 6
t
one 1
two 2
three 3
four 4
five 5
six 6
dtype: int64
'six' in t
True
'seven' in t
# t['seven'] : error ocuurence
False
t.get('seven')
# no return
t.get('seven', 0)
# if seven not in t then return 0
0
Series에 이름 붙이기
name속성을 가지고 있다.
처음 Series를 만들 때 이름을 붙일 수 있다.
s = pd.Series(np.random.randn(5), name="random_nums")
s
Numpy의 Random 함수 3가
0 -1.325324
1 0.848102
2 -0.220157
3 0.635916
4 -0.108576
Name: random_nums, dtype: float64
dtype 뿐만 아니라 Name도 출력
s.name = "임의의 난수"
s
0 -1.325324
1 0.848102
2 -0.220157
3 0.635916
4 -0.108576
Name: 임의의 난수, dtype: float64
III. Pandas로 2차원 데이터 다루기 - dataframe
dataframe?
2-D labeled table
인덱스를 지정할 수도 있음
표나 테이블등의 2차원 데이터를 표현하기에 리스트는 부적합
따라서, 딕셔너리 사용
d = {"height":[1, 2, 3, 4], "weight":[30, 40, 50, 60]}
df = pd.DataFrame(d) #DataFrame의 D와 F가 대문자여야함
df
height
weight
0
1
30
1
2
40
2
3
50
3
4
60
## dtype 확인
df.dtypes
height int64
weight int64
dtype: object
From CSV to DataFrame
CSV : Comma Separated Value
pandas는 csv 파일을 dataframe화 할 수있는 함수를 제공
.read_csv()
를 이용실제로 csv는
,
로 구분된 데이터들로 이루어져있음csv의 각 첫줄에는 각 컬럼에 해당하는 항목이름
# 동일 경로에 country_wise_latest.csv가 존재해야함
covid = pd.read_csv("./country_wise_latest.csv")
covid
Country/Region
Confirmed
Deaths
Recovered
Active
New cases
New deaths
New recovered
Deaths / 100 Cases
Recovered / 100 Cases
Deaths / 100 Recovered
Confirmed last week
1 week change
1 week % increase
WHO Region
0
Afghanistan
36263
1269
25198
9796
106
10
18
3.50
69.49
5.04
35526
737
2.07
Eastern Mediterranean
1
Albania
4880
144
2745
1991
117
6
63
2.95
56.25
5.25
4171
709
17.00
Europe
2
Algeria
27973
1163
18837
7973
616
8
749
4.16
67.34
6.17
23691
4282
18.07
Africa
3
Andorra
907
52
803
52
10
0
0
5.73
88.53
6.48
884
23
2.60
Europe
4
Angola
950
41
242
667
18
1
0
4.32
25.47
16.94
749
201
26.84
Africa
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
182
West Bank and Gaza
10621
78
3752
6791
152
2
0
0.73
35.33
2.08
8916
1705
19.12
Eastern Mediterranean
183
Western Sahara
10
1
8
1
0
0
0
10.00
80.00
12.50
10
0
0.00
Africa
184
Yemen
1691
483
833
375
10
4
36
28.56
49.26
57.98
1619
72
4.45
Eastern Mediterranean
185
Zambia
4552
140
2815
1597
71
1
465
3.08
61.84
4.97
3326
1226
36.86
Africa
186
Zimbabwe
2704
36
542
2126
192
2
24
1.33
20.04
6.64
1713
991
57.85
Africa
187 rows × 15 columns
Pandas 활용 1. 일부분만 관찰하기
head(n)
: 처음 n개의 데이터 참조
# 위에서부터 5개를 관찰하는 방법(함수)
covid.head(5)
Country/Region
Confirmed
Deaths
Recovered
Active
New cases
New deaths
New recovered
Deaths / 100 Cases
Recovered / 100 Cases
Deaths / 100 Recovered
Confirmed last week
1 week change
1 week % increase
WHO Region
0
Afghanistan
36263
1269
25198
9796
106
10
18
3.50
69.49
5.04
35526
737
2.07
Eastern Mediterranean
1
Albania
4880
144
2745
1991
117
6
63
2.95
56.25
5.25
4171
709
17.00
Europe
2
Algeria
27973
1163
18837
7973
616
8
749
4.16
67.34
6.17
23691
4282
18.07
Africa
3
Andorra
907
52
803
52
10
0
0
5.73
88.53
6.48
884
23
2.60
Europe
4
Angola
950
41
242
667
18
1
0
4.32
25.47
16.94
749
201
26.84
Africa
tail(n)
: 마지막 n개의 데이터를 참조
# 아래에서부터 5개를 관찰하는 방법(함수)
covid.tail(5)
Country/Region
Confirmed
Deaths
Recovered
Active
New cases
New deaths
New recovered
Deaths / 100 Cases
Recovered / 100 Cases
Deaths / 100 Recovered
Confirmed last week
1 week change
1 week % increase
WHO Region
182
West Bank and Gaza
10621
78
3752
6791
152
2
0
0.73
35.33
2.08
8916
1705
19.12
Eastern Mediterranean
183
Western Sahara
10
1
8
1
0
0
0
10.00
80.00
12.50
10
0
0.00
Africa
184
Yemen
1691
483
833
375
10
4
36
28.56
49.26
57.98
1619
72
4.45
Eastern Mediterranean
185
Zambia
4552
140
2815
1597
71
1
465
3.08
61.84
4.97
3326
1226
36.86
Africa
186
Zimbabwe
2704
36
542
2126
192
2
24
1.33
20.04
6.64
1713
991
57.85
Africa
Pandas 활용 2. 데이터 접근하기
df['column_name']
ordf.column_name
covid['Active'].head(3)
0 9796
1 1991
2 7973
Name: Active, dtype: int64
covid.Active.head(3)
0 9796
1 1991
2 7973
Name: Active, dtype: int64
column name을 attribute로 접근할 때에는 spacebar가 적용된 변수명은 적용하지 못하는 차이가 있다.
ex) covid.Who Region
O : covid["Who Region"]
X : covid.Who Region
Honey Tip! Dataframe의 각 column은 "Series"이다!
covid['Confirmed'][0]
36263
covid['Confirmed'][1:5]
1 4880
2 27973
3 907
4 950
Name: Confirmed, dtype: int64
Pandas 활용 3. "조건"을 이용해서 데이터 접근하기
# 신규 확진자가 100명이 넘는 나라를 찾아보자!
# 해당하는 column은 New cases
covid[covid['New cases'] > 100].head(3)
Country/Region
Confirmed
Deaths
Recovered
Active
New cases
New deaths
New recovered
Deaths / 100 Cases
Recovered / 100 Cases
Deaths / 100 Recovered
Confirmed last week
1 week change
1 week % increase
WHO Region
0
Afghanistan
36263
1269
25198
9796
106
10
18
3.50
69.49
5.04
35526
737
2.07
Eastern Mediterranean
1
Albania
4880
144
2745
1991
117
6
63
2.95
56.25
5.25
4171
709
17.00
Europe
2
Algeria
27973
1163
18837
7973
616
8
749
4.16
67.34
6.17
23691
4282
18.07
Africa
# unique() : 자료의 범주를 중복 없이 출력
covid['WHO Region'].unique()
array(['Eastern Mediterranean', 'Europe', 'Africa', 'Americas',
'Western Pacific', 'South-East Asia'], dtype=object)
# WHO 지역이 동남아시아인 나라 찾기
covid[covid['WHO Region'] == 'South-East Asia'].head(3)
Country/Region
Confirmed
Deaths
Recovered
Active
New cases
New deaths
New recovered
Deaths / 100 Cases
Recovered / 100 Cases
Deaths / 100 Recovered
Confirmed last week
1 week change
1 week % increase
WHO Region
13
Bangladesh
226225
2965
125683
97577
2772
37
1801
1.31
55.56
2.36
207453
18772
9.05
South-East Asia
19
Bhutan
99
0
86
13
4
0
1
0.00
86.87
0.00
90
9
10.00
South-East Asia
27
Burma
350
6
292
52
0
0
2
1.71
83.43
2.05
341
9
2.64
South-East Asia
Pandas 활용 4. 행을 기준으로 데이터 접근하기
# 예시 데이터 - 도서관 정보
books_dict = {"Available":[True, False, False], "Location":[102, 215, 323], " Genre":["Programming", "Physics", "Math"]}
books_df = pd.DataFrame(books_dict, index=["버그란 무엇인가", "두근두근 물리학", "미분해줘 홈즈"])
books_df
Available
Location
Genre
버그란 무엇인가
True
102
Programming
두근두근 물리학
False
215
Physics
미분해줘 홈즈
False
323
Math
인덱스를 이용해서 가져오기 : loc[row, col]
loc[row, col]
books_df.loc["버그란 무엇인가"]
Available True
Location 102
Genre Programming
Name: 버그란 무엇인가, dtype: object
type(books_df.loc["버그란 무엇인가"])
pandas.core.series.Series
# "미분해줘 홈즈" 책이 대출 가능한지?
books_df.loc["미분해줘 홈즈", 'Available']
False
숫자 인덱스를 이용해서 가져오기 : `.iloc[rowidx, colidx]
# 인덱스 0행, 1열
books_df.iloc[0, 1]
102
# 인덱스 1행, 0~1열
books_df.iloc[1, 0:2]
Available False
Location 215
Name: 두근두근 물리학, dtype: object
Pandas 활용 5. groupby
Split : 특정한 "기준"을 바탕으로 DataFrame을 분할
Apply : 통계함수 - sum(), mean(), median(), - 을 적용해서 각 데이터를 압축
Combine : Apply된 결과를 바탕으로 새로운 Series를 생성 (group_key : applied_value)
.groupby()
covid.head(5)
Country/Region
Confirmed
Deaths
Recovered
Active
New cases
New deaths
New recovered
Deaths / 100 Cases
Recovered / 100 Cases
Deaths / 100 Recovered
Confirmed last week
1 week change
1 week % increase
WHO Region
0
Afghanistan
36263
1269
25198
9796
106
10
18
3.50
69.49
5.04
35526
737
2.07
Eastern Mediterranean
1
Albania
4880
144
2745
1991
117
6
63
2.95
56.25
5.25
4171
709
17.00
Europe
2
Algeria
27973
1163
18837
7973
616
8
749
4.16
67.34
6.17
23691
4282
18.07
Africa
3
Andorra
907
52
803
52
10
0
0
5.73
88.53
6.48
884
23
2.60
Europe
4
Angola
950
41
242
667
18
1
0
4.32
25.47
16.94
749
201
26.84
Africa
# WHO Region별 확진자수
# 1. covid에서 확진자 수 column만 추출한다
# 2. 이를 covid WHO Region을 기준으로 groupby한다
covid_by_region = covid['Confirmed'].groupby(by=covid["WHO Region"])
covid_by_region
<pandas.core.groupby.generic.SeriesGroupBy object at 0x00000205A35511C8>
covid_by_region.sum()
WHO Region
Africa 723207
Americas 8839286
Eastern Mediterranean 1490744
Europe 3299523
South-East Asia 1835297
Western Pacific 292428
Name: Confirmed, dtype: int64
# 국가당 감영자 수
covid_by_region.mean()
WHO Region
Africa 15066.812500
Americas 252551.028571
Eastern Mediterranean 67761.090909
Europe 58920.053571
South-East Asia 183529.700000
Western Pacific 18276.750000
Name: Confirmed, dtype: float64
Mission:
1. covid 데이터에서 100 case 대비 사망률(Deaths / 100 Cases
)이 가장 높은 국가는?
Deaths / 100 Cases
)이 가장 높은 국가는?covid.iloc[covid['Deaths / 100 Cases'].idxmax(), 0]
'Yemen'
2. covid 데이터에서 신규 확진자가 없는 나라 중 WHO Region이 'Europe'를 모두 출력하면?
Hint : 한 줄에 동시에 두가지 조건을 Apply하는 경우 Warning이 발생할 수 있습니다.
cond = covid[covid['New cases'] == 0]
cond[cond['WHO Region'] == 'Europe']
Country/Region
Confirmed
Deaths
Recovered
Active
New cases
New deaths
New recovered
Deaths / 100 Cases
Recovered / 100 Cases
Deaths / 100 Recovered
Confirmed last week
1 week change
1 week % increase
WHO Region
56
Estonia
2034
69
1923
42
0
0
1
3.39
94.54
3.59
2021
13
0.64
Europe
75
Holy See
12
0
12
0
0
0
0
0.00
100.00
0.00
12
0
0.00
Europe
95
Latvia
1219
31
1045
143
0
0
0
2.54
85.73
2.97
1192
27
2.27
Europe
100
Liechtenstein
86
1
81
4
0
0
0
1.16
94.19
1.23
86
0
0.00
Europe
113
Monaco
116
4
104
8
0
0
0
3.45
89.66
3.85
109
7
6.42
Europe
143
San Marino
699
42
657
0
0
0
0
6.01
93.99
6.39
699
0
0.00
Europe
157
Spain
272421
28432
150376
93613
0
0
0
10.44
55.20
18.91
264836
7585
2.86
Europe
3. 다음 데이터를 이용해 각 Region별로 아보카도가 가장 비싼 평균가격(AveragePrice)을 출력하면?
avocado = pd.read_csv("./avocado.csv")
avocado
Unnamed: 0
Date
AveragePrice
Total Volume
4046
4225
4770
Total Bags
Small Bags
Large Bags
XLarge Bags
type
year
region
0
0
2015-12-27
1.33
64236.62
1036.74
54454.85
48.16
8696.87
8603.62
93.25
0.0
conventional
2015
Albany
1
1
2015-12-20
1.35
54876.98
674.28
44638.81
58.33
9505.56
9408.07
97.49
0.0
conventional
2015
Albany
2
2
2015-12-13
0.93
118220.22
794.70
109149.67
130.50
8145.35
8042.21
103.14
0.0
conventional
2015
Albany
3
3
2015-12-06
1.08
78992.15
1132.00
71976.41
72.58
5811.16
5677.40
133.76
0.0
conventional
2015
Albany
4
4
2015-11-29
1.28
51039.60
941.48
43838.39
75.78
6183.95
5986.26
197.69
0.0
conventional
2015
Albany
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
18244
7
2018-02-04
1.63
17074.83
2046.96
1529.20
0.00
13498.67
13066.82
431.85
0.0
organic
2018
WestTexNewMexico
18245
8
2018-01-28
1.71
13888.04
1191.70
3431.50
0.00
9264.84
8940.04
324.80
0.0
organic
2018
WestTexNewMexico
18246
9
2018-01-21
1.87
13766.76
1191.92
2452.79
727.94
9394.11
9351.80
42.31
0.0
organic
2018
WestTexNewMexico
18247
10
2018-01-14
1.93
16205.22
1527.63
2981.04
727.01
10969.54
10919.54
50.00
0.0
organic
2018
WestTexNewMexico
18248
11
2018-01-07
1.62
17489.58
2894.77
2356.13
224.53
12014.15
11988.14
26.01
0.0
organic
2018
WestTexNewMexico
18249 rows × 14 columns
regions = avocado['region'].unique()
for region in regions:
cond = avocado[avocado['region'] == region]
print(avocado.iloc[cond['AveragePrice'].idxmax(),:])
오토마타와 컴파일러
CFG : removing ambiguous grammar
Context Free Grammar는 구문 분석을 하는데 있어서 효율을 상당히 떨어뜨리는 경우에 효율적인 구문분석이 이루어지도록 주어진 문법을 적당한 문법으로 바꾸는 문법 변환을 필요로 한다. 모호한 문법의 제거 방법은 다음과 같다.
불필요한 생성규칙의 제거
ε-생성규칙의 제거
단일 생성규칙의 제거
좌인수분해
좌재귀 제거
이를 구현하면 다음과 같다. (코드를 보기 전에 언을 하자면, 구현된 제거는 불필요한 생성규칙의 제거, ε-생성규칙의 제거, 단일 생성규칙의 제거 까지이며 이마저도 완벽하게 구현되지 않았다. 지금까지 찾은 반례로는 S -> ABC, A -> B | a, B -> C | b, C -> A | c 와 같은 순환 코드에 대해서 작동하지 않는다. 그 외에는 잘 작동한다고 생각이 들지만 오류를 발생시키는 반례가 충분히 있을 것이라 예상한다. 좌인수분해와 좌재귀제거는 코드가 너무 지저분해져 능력을 벗어나는 일이라고 생각해 포기했다.)
#
# data = 2020.12.15
# author = sangmandu at Dankook Univ.
# program = Effective Context Free Grammar in that removing unnecessary(ambiguous) grammar
# language = python
#
#
# P = Set of grammar
# S = StartSymbol
# Z = S' (alternative S that express ε)
# [A-Z] = Non terminal
# [a-z][0-9][._()] = Terminal
# ε = null
#
def initialization(P):
dic = {}
Vn, Vt = set(), set()
for grammar in P:
src, dst = grammar.split("->")
Vn.add(src)
dst = dst.split("|")
dic.setdefault(src, [])
for d in dst:
dic[src].append(d)
for letter in d:
if letter.isupper():
Vn.add(letter)
else:
Vt.add(letter)
printResult(initialization.__name__, [dic, Vn, Vt])
return dic, Vn, Vt
def refreshVnVt(dic):
Vn, Vt = set(), set()
for key, values in dic.items():
Vn.add(key)
for value in values:
for letter in value:
if not letter.isupper():
Vt.add(letter)
return Vn, Vt
def checkNeed(dic, Vn, flag=1):
stack = ['S']
_Vn = set()
while stack:
nt = stack.pop(0)
_Vn.add(nt)
for symbol in dic[nt]:
for letter in symbol:
if letter.isupper() and letter not in _Vn and letter not in stack:
stack.append(letter)
for nt in Vn - _Vn:
del dic[nt]
Vn, Vt = refreshVnVt(dic)
if flag:
printResult(checkNeed.__name__, [dic, Vn, Vt])
return Vn, Vt
def checkNull(dic, Vn, Vt):
if 'ε' not in Vt: return Vn, Vt
_Nt = []
for nt in Vn:
if 'ε' in dic[nt]:
_Nt.append(nt)
size = 0
while len(_Nt) != size:
size = len(_Nt)
for nt in _Nt:
for key, value in dic.items():
for v in value:
if nt in v and key not in _Nt:
_Nt.append(key)
for key in Vn:
stack = dic[key][:]
dup = []
while stack:
value = stack.pop(0)
if value == "ε":
continue
if not value.isupper():
dic[key].append(value)
for idx, letter in enumerate(value):
if letter in _Nt and (value, idx) not in dup:
stack.append(value)
dup.append((value, idx))
stack.append(value[:idx]+value[idx+1:])
else:
if value and value not in dic[key]:
dic[key].append(value)
for key, value in dic.items():
dic[key] = list(set(value))
while "ε" in dic[key]:
dic[key].remove("ε")
while "" in dic[key]:
dic[key].remove("")
dic["Z"], dic["S"] = dic["S"], ["Z", "ε"]
Vn, Vt = refreshVnVt(dic)
printResult(checkNull.__name__, [dic, Vn, Vt])
return Vn, Vt
def checkNtoN(dic):
from itertools import product
temp = 0
while True:
length = sum([len(dic[x]) for x in dic.keys()])
if temp == length: break
temp = length
replace = []
for key, values in dic.items():
for value in values:
if all([letter.isupper() for letter in value]):
replace.append((key, value))
for key, value in replace:
dic[key].remove(value)
addvalue = []
for letter in value:
addvalue.append(dic[letter])
for item in list(product(*addvalue)):
dic[key].append(''.join(item))
Vn, Vt = refreshVnVt(dic)
Vn, Vt = checkNeed(dic, Vn, 0)
printResult(checkNtoN.__name__, [dic, Vn, Vt])
return Vn, Vt
def checkLeftRecur(dic, Vn):
Vn, Vt = refreshVnVt(dic)
printResult(checkLeftRecur.__name__, [dic, Vn, Vt])
return Vn, Vt
def checkLeftFactor(dic, Vn):
Vn, Vt = refreshVnVt(dic)
printResult(checkLeftFactor.__name__, [dic, Vn, Vt])
return Vn, Vt
def printResult(funcName, arr):
print()
print(f"func {funcName}")
p = ["dic", "Vn", "Vt"]
for idx, val in enumerate(arr):
print(f"{p[idx]} = {val}")
P1 = {"S->aB", "A->aB|aC", "B->C|Ee|Bb", "C->b", "D->c", "E->fEgE|gEfE|ε"}
P2 = {"S->ABCD", "A->B|a", "B->C|b", "C->c|ε", "D->Dd"}
P3 = {"S->A|B", "A->C", "C->c", "B->ED|b", "E->e|f", "D->d"}
for P in [P1, P2, P3]:
print("---------------")
print(P)
dic, Vn, Vt = initialization(P)
Vn, Vt = checkNeed(dic, Vn)
Vn, Vt = checkNull(dic, Vn, Vt)
Vn, Vt = checkNtoN(dic)
Vn, Vt = checkLeftFactor(dic, Vn)
Vn, Vt = checkLeftRecur(dic, Vn)
print("---------------")
Last updated
Was this helpful?