def solution(n, arr1, arr2):
answer = []
for i, j in zip(arr1, arr2):
answer.append(str(bin(i|j))[2:].rjust(n,' ').replace('1','#').replace('0',' '))
return answer
문자열.rjust(전체 자리 숫자, 공백이 있을 경우 공백을 채울 텍스트)# 1
def solution(n, arr1, arr2):
return [str(bin(i | j))[2:].rjust(n,' ').replace('1','#').replace('0',' ') for i,j in zip(arr1,arr2)]
# 2
solution = lambda n, arr1, arr2: ([''.join(map(lambda x: '#' if x=='1' else ' ', "{0:b}".format(row).zfill(n))) for row in (a|b for a, b in zip(arr1, arr2))])
zfill() 써도 됨def solution(n, arr1, arr2):
answer = []
for i, j in zip(arr1, arr2):
answer.append(str(bin(i|j))[2:].zfill(n).replace('1','#').replace('0',' '))
return answer
f'{x:016b}'로 x(=a|b)를 16자리 이진수 문자열로 만들어준다.' #'[0]으로 공백이 문자열에 추가되고 1이면 ' #'[1]이 돼서 #이 추가됨def solution(n, *maps):
return [line(n, a | b) for a, b in zip(*maps)]
def line(n, x):
return ''.join(' #'[int(i)] for i in f'{x:016b}'[-n:])
# 하나라도 벽인 부분은 전체 지도에서도 벽 (벽: 1)
# 모두 공백인 부분은 전체 지도에서도 공백 (공백: 0)
def adjust_length(binary, n):
while len(binary)<n:
binary = '0' + binary
return binary
def solution(n, arr1, arr2):
answer = []
for i in range(n):
real_map = ''
map1 = bin(arr1[i])[2:]
map2 = bin(arr2[i])[2:]
map1 = adjust_length(map1, n)
map2 = adjust_length(map2, n)
for j in range(n):
if map1[j]=='1' or map2[j]=='1':
real_map += '#'
elif map1[j]=='0' and map2[j]=='0':
real_map += ' '
answer.append(real_map)
return answer
SELECT
u.user_id AS buyer_id
, u.join_date
, COUNT(o.order_id) AS orders_in_2019
FROM
Users AS u
LEFT JOIN Orders as o
ON u.user_id = o.buyer_id
AND YEAR(order_date) = 2019
GROUP BY
u.user_id
;
SELECT u.user_id AS buyer_id, u.join_date AS join_date,
SUM(CASE WHEN YEAR(o.order_date)=2019 THEN 1 ELSE 0 END) AS orders_in_2019
FROM Users u
LEFT JOIN Orders o
ON u.user_id=o.buyer_id
GROUP BY u.user_id
;
SELECT buyer_id, join_date, COUNT(*) AS orders_in_2019
FROM Orders
JOIN Users ON buyer_id=user_id
WHERE YEAR(order_date) = 2019
GROUP BY buyer_id
UNION
SELECT user_id AS buyer_id, join_date, 0 AS orders_in_2019 FROM Users
WHERE user_id NOT IN (SELECT DISTINCT buyer_id FROM Orders WHERE YEAR(order_date) = 2019)
WITH OrderCount AS (
SELECT buyer_id, COUNT(*) as order_count
FROM Orders
WHERE order_date >= '2019-01-01' AND order_date <= '2019-12-31'
GROUP BY buyer_id
)
SELECT u.user_id as buyer_id, u.join_date, COALESCE(
(
SELECT o.order_count
FROM OrderCount o
WHERE o.buyer_id = u.user_id
),
0
) AS orders_in_2019
FROM Users u
;







# 라이브러리 불러오기
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 경고창 무시
import warnings
warnings.filterwarnings("ignore")
# 데이터 불러오기 (data)
data = pd.read_csv("./data/melb_data.csv")
data
# 정답 -> Price 집값 데이터 (연속형 -> 회귀 학습)

데이터프레임의 크기가 커서 열과 행이 생략된 상태로 출력됨 -> 열을 다 보고 싶은데 어떨게 하면 될까?
pd.set_option("display.max_columns", None): 전체 열 출력pd.set_option("display.max_rows", None): 전체 행 출력pd.reset_option("all"): 전체 설정 초기화pd.reset_option("display.max_columns"): 한 개의 설정만 초기화할 때(컬럼 설정 초기화)집값 데이터 컬럼 설명
| 컬럼명 | 설명 |
|---|---|
| Suburb | 주택이 위치한 교외 지역의 이름 |
| Address | 주택의 주소 |
| Rooms | 주택의 방 개수 |
| Type | 주택 유형 (h: 주택, u: 유닛, t: 타운하우스) |
| Price | 주택 가격(호주 달러) |
| Method | 판매 방법 (S: 매매, SP: 매매 후 가격 공개, PI: 경매 전에 가격, VB: 경매 후 가격 공개) |
| SellerG | 판매 대행 부동산 중개인의 이름 |
| Date | 판매 날짜 |
| Distance | 주택이 CBD (중심 업무 지구)에서 떨어진 거리 (킬로미터 단위) |
| Postcode | 우편번호 |
| Bedroom2 | 주택의 침실 개수 (2개의 침실을 갖춘 주택) |
| Bathroom | 주택의 욕실 개수 |
| Car | 주차 가능한 자동차 수 |
| Landsize | 대지 면적 (평방 미터 단위) |
| BuildingArea | 건축 면적 (평방 미터 단위) |
| YearBuilt | 주택이 건축된 연도 |
| CouncilArea | 관할 구역 |
| Lattitude | 주택의 위도 |
| Longtitude | 주택의 경도 |
| Regionname | 지역 이름 |
| Propertycount | 지역 내의 부동산 개수 |
→ 정답(y)이 되는 컬럼: Price
# 기본 정보
data.info()
# 결측치가 있는 컬럼 확인 -> EDA를 통해 채울지 결정
data.isna().sum().sort_values(ascending=False)
# 기술통계량 확인
data.describe().T # 수치 데이터만 확인 가능
# 텍스트 데이터(범주 데이터)는 하나씩 따로 확인해보기

# 부동소수점 일반 숫자로 출력하는 방법
pd.options.display.float_format = '{:.2f}'.format
data["Type"].unique()
# 출력:
# array(['h', 'u', 't'], dtype=object)
# 각 타입들의 개수를 확인
data["Type"].value_counts()
| Type | count |
|---|---|
| h | 9449 |
| u | 3017 |
| t | 1114 |
# 주택 타입별 가격 평균 확인 -> groupby
data["Price"].groupby(data["Type"]).mean()
# 방법은 다양함
# 사용할 컬럼.groupby(기준이 되는 컬럼).함수()
data[["Type", "Price"]].groupby(["Type"]).mean()
# agg() 함수도 가능
data.groupby(["Type"])["Price"].agg('mean')
# Pivot table로도 가능하지만 보통 groupby를 더 많이 씀
data.pivot_table(index="Type", values="Price", aggfunc="mean")
| Type | Price |
|---|---|
| h | 1242664.76 |
| u | 933735.05 |
| t | 605127.48 |
# 시각화 -> pandas에서 제공해주는 간략하게 그래프 그리는 방법
data[["Type", "Price"]].groupby(["Type"]).mean().plot(kind="bar")
# 범주 형태의 데이터는 주로 막대그래프를 그림(or 히스토그램)

# x축 글씨 방향 돌리기
data[["Type", "Price"]].groupby(["Type"]).mean().plot(kind="bar")
plt.xticks(rotation=0)

# 상관계수 확인
data.corr(numeric_only=True)

# 내림차순(절대값)으로 Price 컬럼 정렬
data.corr(numeric_only=True).abs().sort_values(by="Price", ascending=False)["Price"]
# 이렇게 써도 됨
data.corr(numeric_only=True)["Price"].abs().sort_values(ascending=False)
# Price에 영향을 가장 많이 미치고 있는 Rooms 확인해보기

df_plus = data.corr(numeric_only=True)
sns.clustermap(df_plus,
annot = True, # 실제 값 화면에 나타내기
cmap = 'RdYlBu_r', # Red, Yellow, Blue 색상으로 표시
vmin = -1, vmax = 1, #컬러차트 -1 ~ 1 범위로 표시
)

# 그림 사이즈 지정
fig, ax = plt.subplots(figsize=(7,7))
# 삼각형 마스크를 만든다(위 쪽 삼각형에 True, 아래 삼각형에 False)
mask = np.zeros_like(df_plus, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True
# 히트맵을 그린다
sns.heatmap(df_plus,
cmap = 'RdYlBu_r',
annot = True, # 실제 값을 표시한다
mask=mask, # 표시하지 않을 마스크 부분을 지정한다
linewidths=.5, # 경계면 실선으로 구분하기
cbar_kws={"shrink": .5},# 컬러바 크기 절반으로 줄이기
vmin = -1,vmax = 1 # 컬러바 범위 -1 ~ 1
)
plt.show()

# 상자 그림 -> 데이터의 분포 확인 -> 이상치 여부 확인도 가능하다~
fig1, ax1 = plt.subplots(figsize = (8,12))
sns.boxplot(data=data, x="Rooms", y="Price", ax=ax1)
plt.show()
# 방의 개수가 증가할수록 주택가격이 상승
# 특정 지점 이상에서는 가격 상승이 정체됨
# 박스의 크기가 크다는 것은 방 개수에 따른 가격 변동성이 큰 것을 의미
# 방의 개수가 많아질수록 가격 변동성이 크다!



# 방이 3개인 데이터의 이상치 개수 확인
# 방이 3개인 데이터만 추출
rooms_3 = data[data["Rooms"]==3]
# 이상치는 박스 플롯에서 최댓값보다 클 때 (상위경계값: Q3 + 1.5*IQR)
# IQR: 4분위수 범위 (Q3-Q1)
Q1 = rooms_3["Price"].quantile(0.25)
Q3 = rooms_3["Price"].quantile(0.75)
IQR = Q3 - Q1
# 이상치 조건
upper_bound = Q3 + 1.5 * IQR
# 이상치 추출 -> 불리언 인덱싱
rooms_3[rooms_3["Price"]>upper_bound]
# 총 173개
# pairplot(data): 변수 간 상관관계를 시각화 -> 분포 확인
sns.pairplot(data[['Rooms','Bedroom2','Bathroom','Lattitude','Distance','Type','Price']])
plt.show()


data["Car"].isna().sum()
# 출력:
# np.int64(62)
data.corr(numeric_only=True)["Car"]

# Type과 Car 데이터 분포 확인
plt.figure(figsize=(9,5))
sns.boxplot(x="Type", y="Car", data=data)
plt.show()
# u에 비해 t, h 순으로 주차 공간이 많은 것을 확인

# Rooms와 Type에 따른 Car 중위수 계산 -> car_mid = data.groupby(["Rooms", "Type"])["Car"].median()
# 단순하게 결측치를 채우는 것이 아니라 값의 상관관계를 통하여 결측치를 채움
# 함수 생성(fill_car) -> 값이 비어있으면 방과 타입에 따라 차 대수를 반환, 값이 있으면 해당 차 대수를 반환
def fill_car(data)->float:
if pd.isna(data["Car"]):
return car_mid.loc[(data["Rooms"], data["Type"])] # ※1
else:
return data["Car"]
# 함수 적용 -> apply()
data["Car"] = data.apply(fill_car, axis=1)
data["Car"].isna().sum()
# 출력:
# np.int64(0)
※1: # titanic의 Age는 pivot_table(→테이블: 행과 열 존재)이었기 때문에 열 이름이 필요했지만 car_mids는 groupby(→단순 계산 결과)의 결과라 단순 값을 한 줄만 추출했기 때문에 필요 없음
data["CouncilArea"].unique()
array(['Yarra', 'Moonee Valley', 'Port Phillip', 'Darebin', 'Hobsons Bay',
'Stonnington', 'Boroondara', 'Monash', 'Glen Eira', 'Whitehorse',
'Maribyrnong', 'Bayside', 'Moreland', 'Manningham', 'Banyule',
'Melbourne', 'Kingston', 'Brimbank', 'Hume', nan, 'Knox',
'Maroondah', 'Casey', 'Melton', 'Greater Dandenong', 'Nillumbik',
'Whittlesea', 'Frankston', 'Macedon Ranges', 'Yarra Ranges',
'Wyndham', 'Cardinia', 'Unavailable', 'Moorabool'], dtype=object)
len(data["CouncilArea"].unique())
# 출력:
# 34
# 관할구역 그래프 그리기~
# 각 값들의 개수 확인
data["CouncilArea"].value_counts()
# 데이터 개수를 세어 그래프 추출 -> countplot
plt.subplots()
sns.countplot(y="CouncilArea", data=data, order=data["CouncilArea"].value_counts().index)
plt.show()
# 최빈값으로 채울까? -> 최빈값으로 채운다면 Moreland, Boroondara... 둘 중에 뭘로 채우지?
# 다른 컬럼과의 연관성 파악 -> 데이터 유추하여 결측치 채움 -> Suburb, Postcode, Regionname, Address 등
# Suburb 데이터를 활용하여 CouncilArea 결측치 처리
# 지역에 따른 매칭을 위해 최빈값으로 두 값을 매칭
mode_co = data.groupby("Suburb")["CouncilArea"].agg(pd.Series.mode)
# 관할 구역값이 있으면 그 값을 추출, 없으면 Suburb에 해당하는 값을 추출
def fill_council (row):
if pd.isna(row["CouncilArea"]):
return mode_co[row["Suburb"]]
else:
return row["CouncilArea"]
data["CouncilArea"] = data.apply(fill_council, axis=1)
data["CouncilArea"].isna().sum()
data.corr(numeric_only=True)["Price"].sort_values(ascending=False)
# 정답(집 가격)에 영향을 많이 미치는 컬럼들 선택
feature_names = ["Rooms", "Bedroom2", "Bathroom", "Car", "Distance", "Type", "CouncilArea", "Lattitude", "Longtitude"]
# 문제와 정답 분리
X = data[feature_names] # 인덱싱 대괄호 2개와 동일 효과
y = data["Price"]
X["CouncilArea"].dtype
# 출력:
# dtype('O') → object라는 뜻
# X["CouncilArea"].unique() 확인 시 -> 넘파이 배열 형태로 저장 -> 확인 불가
# 데이터를 str 형태로 형변환
X["CouncilArea"] = X["CouncilArea"].astype(str)
X["CouncilArea"].unique()
# '[]' 없애줘야 함!
# [] 데이터가 있는 7개의 행 삭제 후 인코딩 진행 -> CouncilArea로 채워줘도 되지만 삭제 연습할 겸 지워보기
dd = X[X["CouncilArea"]=="[]"]
# [] 값이 들어 있는 인덱스를 통해 삭제 -> 문제, 정답 모두 삭제하기~
X.drop(dd.index, inplace=True)
y.drop(dd.index, inplace=True)
# 원핫 인코딩 -> pd.get_dummies()
X_one_hot = pd.get_dummies(X, dtype="int")
train_test_split()# 분리 도구 -> train_test_split()
# 랜덤 규칙 7 사용하기
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_one_hot, y, test_size=0.3, random_state=7)
# 데이터 크기확인
print(X_train.shape, y_train.shape)
print(X_test.shape, y_test.shape)
from sklearn.linear_model import LinearRegression
# 모델 객체 생성
linear_model = LinearRegression()
# 모델 학습
linear_model.fit(X_train, y_train)
# 모델 예측
y_pred = linear_model.predict(X_test)
y_pred


# 선형 모델의 원리: 데이터를 잘 대표하는 직선을 찾아나가는 과정
# y = wx + b (y = w1x1 + w2x2 + w3x3 + ... + wpxp + b)
# 모델의 가중치(w), y절편(b)
w = linear_model.coef_
b = linear_model.intercept_
print("가중치(w):", w)
print("y절편(b):", b)
print(len(w))
print(X_one_hot.shape)

→ p개의 가중치가 생김
>> [Out]
가중치(w): [ 1.59878350e+05 1.94650326e+04 1.76017553e+05 4.20028467e+04
-3.41832898e+04 -1.93532844e+06 -2.55260954e+05 2.89889911e+05
-4.44002459e+04 -2.45489665e+05 8.34855253e+03 3.87318781e+05
4.62733753e+05 -3.77694557e+05 -3.66776004e+04 -2.66944949e+05
7.41208976e+02 -2.31974862e+05 -1.39791963e+04 -2.51684700e+05
-2.60774899e+05 -7.62707974e+04 -1.49010867e+05 -1.25038573e+05
9.60451191e+05 1.30302856e+05 -2.88579328e+05 1.11700332e+05
-6.89389116e+03 -2.17451901e+05 6.37393748e+03 -5.12408279e+04
2.07753815e+05 -1.18329616e+05 4.07312711e+04 1.37533027e+05
2.82986271e+05 -4.07453626e-10 1.90005263e+05 -8.15858302e+02
-7.38655714e+05 3.45421553e+04 2.50495723e+05]
y절편(b): -35771502.19889437
43
(13573, 43)
각 가중치를 해석하는 방법
숫자가 클수록 주택 가격에 영향을 크게 미친다!
# 모델 평가
linear_model.score(X_test, y_test)
# 회귀는 어떻게 해석?
# 분류: score 결과값이 accuracy(정확도) -> O, X의 비율
# 회귀는 O, X로 낼 수가 없어요... 이 score는 mse가 아닙니다!
# 그럼 회귀의 score는 뭔가요 -> r2
from sklearn.metrics import r2_score
r2 = r2_score(y_test, y_pred)
print("linear_model의 r2:", r2)
print("linear_model의 score:", linear_model.score(X_test, y_test))
linear_model의 r2: 0.6210579795833158
linear_model의 score: 0.6210579795833158

# 회귀 모델은 분류 모델처럼 맞았다/틀렸다를 O/X로 확인할 수가 없음
# 얼마나 틀렸니? 오차 정도를 평가 지표로 활용 -> MSE(mean_square_error)
# mse 구하기!
from sklearn.metrics import mean_squared_error
# mean_squared_error(실제값, 예측값)
mse = mean_squared_error(y_test, y_pred)
print("linear_model의 mse:", mse)
# 천오백억 달러의 오차? -> 평균"제곱"오차라 달러^2임 -> 따라서 루트를 씌워줘야 단위가 돌아옴!
# RMSE -> MSE에 루트를 씌운 값
rmse = np.sqrt(mse)
print("linear_model의 rmse:", rmse)
# 단위까지 제곱해버려서 평가 때 너무 불편해요...
# 그럼 처음부터 제곱 안 하고 구하면 되지!: mean_absolute_error -> 절댓값
from sklearn.metrics import mean_absolute_error
mae = mean_absolute_error(y_test, y_pred)
print("linear_model의 mae:", mae)
linear_model의 mse: 159095759804.25632
linear_model의 rmse: 398868.0982533654
linear_model의 mae: 260501.7287048834

회귀 → 오차 기반 학습 & 오차 기반 평가

mean_absolute_errormean_squared_error





# 경사하강법 그래프 작성을 위하여 간단한 성적 데이터 생성
# 공부 시간에 따른 성적
score = pd.DataFrame(
{"시간": [2, 4, 8, 9]
, "성적": [20, 40, 80, 90]}
, index = ["동인", "원희", "후상", "은지"]
)
# LinearRegression() -> 모델을 활용하여 성적 예측
# 모델 객체 생성
score_model = LinearRegression()
# 모델 학습 -> 문제 데이터는 항상 2차원!
# 문제: 시간(2차원), 정답: 성적(1차원)
X = score[['시간']]
y = score['성적']
lr_model.fit(X,y)
# 모델 예측 -> 7시간을 공부했을 때 점수를 예측
lr_model.predict([[7]])
# 가중치와 절편 출력
# y = 10x + 0
w = lr_model.coef_
b = lr_model.intercept_
print("가중치(w):", w)
print("절편(b):", b)
# 가설함수 h(x)
def h(w, x):
return w*x + 0
# 비용함수, 손실함수 (mse)
def loss (data, target, weight):
# 예측할 데이터의 X: data, 실제 답: target, 가중치: weight
y_pre = h(weight, data)
mse = np.mean((target - y_pre)**2)
return mse
# 예측한 가중치가 10이라면:
loss(score["시간"], score["성적"], 10) # np.float64(0.0)
# 예측한 가중치가 5라면:
loss(score["시간"], score["성적"], 5) # np.float64(1031.25)
# 예측한 가중치가 15라면:
loss(score["시간"], score["성적"], 15) # np.float64(1031.25)
# x축 범위
w_arr = range(-10, 30+1) # -10 ~ 30
# mse 값 저장
loss_list = []
for w in w_arr:
loss_list.append(loss(score["시간"], score["성적"], w))
# 그래프
plt.subplots()
sns.lineplot(x = w_arr, y = loss_list)
plt.show()

작성 이유
포트폴리오 4가지 관점

| 강사 강의 | ||||
|---|---|---|---|---|
| 메모 | 기능 | 조합 | 정리 | 회고 |
| 주제 | ||||
| 코드 |
