티스토리 뷰
SQL 코드카타
Q150. Revising Aggregations - The Count Function
1. 문제 링크: https://www.hackerrank.com/challenges/revising-aggregations-the-count-function/problem
2. 정답 코드:
SELECT COUNT(*)
FROM CITY
WHERE POPULATION > 100000;
Q151. Revising Aggregations - The Sum Function
1. 문제 링크: https://www.hackerrank.com/challenges/revising-aggregations-sum/problem
2. 정답 코드:
SELECT SUM(POPULATION)
FROM CITY
WHERE District = 'California';
Q152. Revising Aggregations - Averages
1. 문제 링크: https://www.hackerrank.com/challenges/revising-aggregations-the-average-function/problem
2. 정답 코드:
SELECT ROUND(AVG(POPULATION),3)
FROM CITY
WHERE District = 'California'
A. SQL (Q1–Q4)
Q1. AVG와 NULL 🧰 필수
테이블 t_score가 아래와 같을 때, 결과로 올바른 것은?
| score |
| 5 |
| NULL |
| 3 |
SELECT AVG(score) AS avg_score
FROM t_score;
A. 2.666…
B. 4.0
C. 8.0
D. NULL
Q2. BETWEEN 동작 🧰 필수
MySQL에서 BETWEEN에 대한 설명으로 가장 올바른 것은?
A. 시작값만 포함하고 끝값은 포함하지 않는다
B. 시작값/끝값을 모두 포함한다
C. 문자열에서는 동작하지 않는다
D. NULL이 있으면 항상 에러가 난다
Q3. 2026-01-03 Comedy 평점 리스트 🧰 필수
아래 조건을 만족하는 평점 리스트를 출력하는 SQL을 작성하세요.
- 대상 날짜: rated_at의 날짜가 '2026-01-03'
- 영화 조건: movies.genre = 'Comedy' AND movies.is_available = 1
- 평점 조건: review_status IN ('OK','SUSPECT')
- 평점값 조건: rating이 NULL이 아니어야 함
- 출력 컬럼:
- rated_at, city, title, rating, review_status
- 정렬: city 오름차순, user_id 오름차순
사용 테이블: ratings r / movies m / users u
SELECT
r.rated_at,
u.city,
m.title,
r.rating,
r.review_status
FROM final_test.ratings r
JOIN final_test.users u
ON r.user_id = u.user_id
JOIN final_test.movies m
ON r.movie_id = m.movie_id
WHERE SUBSTR(r.rated_at, 1, 10) = '2026-01-03'
AND m.genre = 'Comedy'
AND m.is_available = 1
AND r.review_status IN ('OK','SUSPECT')
AND r.rating IS NOT NULL
ORDER BY u.city, r.user_id;
# 내가 작성한 쿼리
SELECT
r.rated_at,
u.city,
m.title,
r.rating,
r.review_status
FROM ratings r
JOIN movies m
ON r.movie_id = m.movie_id
JOIN users u
ON r.user_id = u.user_id
WHERE DATE(r.rated_at) = '2026-01-03'
AND m.genre = 'Comedy'
AND m.is_available = 1
AND r.review_status IN ('OK', 'SUSPECT')
AND r.rating IS NOT NULL
ORDER BY u.city ASC, r.user_id ASC;
# 정답 쿼리
Q4. 도시별 평균 평점 TOP 1 🚀 도전
Q3과 동일한 필터 조건으로, 도시별 평균 평점을 구한 뒤 평균이 가장 높은 도시 1개만 출력하세요.
- 출력 컬럼:
- city
- avg_rating (소수 1자리 반올림)
- rating_cnt (해당 조건에 포함된 평점 개수)
- 정렬: avg_rating 내림차순, city 오름차순
- 결과는 1행만
SELECT
u.city,
ROUND(AVG(r.rating), 1) AS avg_rating,
COUNT(r.rating) AS rating_cnt
FROM final_test.ratings r
JOIN final_test.users u
ON r.user_id = u.user_id
JOIN final_test.movies m
ON r.movie_id = m.movie_id
WHERE SUBSTR(r.rated_at, 1, 10) = '2026-01-03'
AND m.genre = 'Comedy'
AND m.is_available = 1
AND r.review_status IN ('OK','SUSPECT')
AND r.rating IS NOT NULL
GROUP BY u.city
ORDER BY avg_rating DESC, u.city ASC
LIMIT 1;
# 내가 작성한 쿼리
SELECT
u.city,
ROUND(AVG(r.rating), 1) AS avg_rating,
COUNT(*) AS rating_cnt
FROM ratings r
JOIN movies m
ON r.movie_id = m.movie_id
JOIN users u
ON r.user_id = u.user_id
WHERE DATE(r.rated_at) = '2026-01-03'
AND m.genre = 'Comedy'
AND m.is_available = 1
AND r.review_status IN ('OK', 'SUSPECT')
AND r.rating IS NOT NULL
GROUP BY u.city
ORDER BY avg_rating DESC, u.city ASC
LIMIT 1;
# 정답 쿼리
B. Python (Q5–Q8)
Q5. set의 길이 🧰 필수
s = {"a", "b", "a"}
print(len(s))
A. 3
B. 2 → 고유 값만 갯수 센다
C. 1
D. 에러
set은 중복 원소가 없는(duplicate 없음) 컬렉션
Q6. 기본 인자 함정 🚀 도전
def add_item(x, items=[]):
items.append(x)
return items
print(add_item(1))
print(add_item(2))
A. [1] / [2]
B. [1] / [1, 2] → 기본 값이 items=[]라고 정의 되어 있어서 append 가능
C. [] / [1, 2]
D. 에러
기본 인자 값은 함수 정의 시 1번만 평가되고, 그 값이 호출 간 재사용된다.
리스트처럼 가변 객체를 수정(append)하면 누적되어 [1] 다음에 [1, 2]가 된다.
Q7. 리뷰 상태가 BAD인지 판별 🧰 필수
아래 조건을 만족하는 함수 is_bad(review_status, rating)를 작성하세요.
- review_status == "BAD" 이면 True
- rating이 None이면 True
- 그 외는 False
예:
- is_bad("OK", 4) → False
- is_bad("BAD", 5) → True
- is_bad("OK", None) → True
def is_bad(review_status, rating):
if (review_status == "BAD") or (rating == None) :
return True
else:
return False
# 내가 작성한 코드
def is_bad(review_status, rating):
if review_status == "BAD":
return True
if rating is None:
return True
return False
# 정답 코드
rating == None 보다는 rating is None을 사용하는 게 권장된다.
또한, else 문으로 False 조건을 주기 보다는, if 문에서 True가 되지 않는다면 False라는 뜻이니까 if 문 밖에서 return False를 해주면 된다!
Q8. None을 무시하고 합 구하기 🧰 필수
리스트 values에서 None은 무시하고 나머지 숫자만 합을 반환하는 함수 sum_ignore_none(values)를 작성하세요.
예:
- sum_ignore_none([1, None, 3]) → 4
def sum_ignore_none(values):
result = 0
for i in values:
if i != None:
result += int(i)
return result
# 내가 작성한 코드
def sum_ignore_none(values):
total = 0
for v in values:
if v is None:
continue
total += v
return total
# 정답 코드
데이터가 복잡해질수록 정답처럼 예외를 먼저 걸러내는 방식이 코드를 읽기에 더 편할 때가 많다! ← if v is None: continue
문제에서 "입력값은 항상 숫자형이다"라고 가정했다면 괜찮지만, 정밀한 계산이 필요한 경우(ex.1.5를 더해야 하는데 1로 바뀌어버림)에는 int()를 빼는 것이 더 안전할 수 있다..!
파이썬에서는 None을 비교할 때 != 보다는 is not 연산자를 사용하는 것을 표준 권장사항으로 두고 있다!!!!!
C. 전처리(Pandas) (Q9–Q14)
Q9. to_numeric + errors="coerce" 🧰 필수
import pandas as pd
s = pd.Series(["3", "x", "5"])
out = pd.to_numeric(s, errors="coerce")
print(out.tolist())
A. [3, 0, 5]
B. [3, "x", 5]
C. [3.0, nan, 5.0] → errors="coerce" a숫자 형태 아니면 None(Nan)으로 바꿔라!
D. 에러
pd.to_numeric(..., errors="coerce")는 숫자로 못 바꾸는 값을 NaN으로 강제 변환한다.
그래서 "x"가 nan이 되어 [3.0, nan, 5.0] 형태가 된다.
Q10. duplicated의 기본 keep 🧰 필수
import pandas as pd
df = pd.DataFrame({"user_id": ["U1", "U1", "U2"]})
print(df.duplicated(subset=["user_id"]).sum())
A. 0
B. 1 → 중복 제거(duplicated)하고 더하기
C. 2
D. 3
duplicated() 기본 동작은 첫 등장만 False, 이후 중복은 True
["U1","U1","U2"]에서 두 번째 U1만 중복 처리되어 합계는 1
Q11. fillna(inplace=True) 반환값 🚀 도전
import pandas as pd
df = pd.DataFrame({"x": [1, None]})
result = df["x"].fillna(0, inplace=True)
print(result)
A. 0
B. [1, 0]
C. None
D. 에러
inplace=True 는 원본을 바꿔라 라는 말이라서 result로 받을 필요가 없음
df 원본은 0으로 바꾸지만 result에는 주는 값이 없음! fillna(inplace=True)는 보통 반환값이 None이 된다.
Q12. 데이터 로드 & 기본 확인 🧰 필수
users.csv, movies.csv, ratings.csv를 불러오고 아래를 수행하세요.
- 각 데이터프레임의 shape 출력
- ratings에서 head(2) 출력
- (권장: ratings는 parse_dates=["rated_at"])
import pandas as pd
movies_df = pd.read_csv("movies.csv")
ratings_df = pd.read_csv("ratings.csv")
users_df = pd.read_csv("users.csv")
print('users:', users_df.shape)
print('movies:', movies_df.shape)
print('ratings:', ratings_df.shape)
print(ratings_df.head(2))
# 내가 작성한 코드
import pandas as pd
users = pd.read_csv("users.csv")
movies = pd.read_csv("movies.csv")
ratings = pd.read_csv("ratings.csv", parse_dates=["rated_at"])
print("users:", users.shape)
print("movies:", movies.shape)
print("ratings:", ratings.shape)
print(ratings.head(2))
# 정답 코드
Q13. 중복 제거 + 숫자 변환 + 병합 + 필터 🧰 필수
아래 순서대로 처리하세요.
- ratings에서 (user_id, movie_id, rated_at) 기준 중복 개수 출력
- 위 기준으로 drop_duplicates(keep="first") 적용
- rating_num 컬럼 생성: pd.to_numeric(rating, errors="coerce")
- movies, users를 차례대로 left merge 해서 df_full 생성
- 아래 조건으로 필터링하여 df_clean 생성
- is_available == 1
- review_status가 OK 또는 SUSPECT
- rating_num이 결측치가 아님
- df_clean의 행 개수 출력
import pandas as pd
movies_df = pd.read_csv("movies.csv")
ratings_df = pd.read_csv("ratings.csv")
users_df = pd.read_csv("users.csv")
print('dup_cnt:', ratings_df.duplicated(subset=['user_id', 'movie_id', 'rated_at']).sum())
ratings_df = ratings_df.drop_duplicates(subset=['user_id', 'movie_id', 'rated_at'], keep="first")
ratings_df['rating_num'] = pd.to_numeric(ratings_df['rating'], errors="coerce")
df_full = ratings_df.merge(movies_df, on="movie_id", how="left")
df_full = df_full.merge(users_df, on="user_id", how="left")
df_clean = df_full[(df_full['is_available'] == 1) & (df_full['review_status'].isin(["OK","SUSPECT"])) & (df_full['rating_num'].isna() != False)]
print('rows:', df_clean.shape[1])
# 내가 작성한 코드
완전 중복: subset 작성 X
부분 중복: subset= ['컬럼1', '컬럼2']
import pandas as pd
users = pd.read_csv("users.csv")
movies = pd.read_csv("movies.csv")
ratings = pd.read_csv("ratings.csv", parse_dates=["rated_at"])
dup_cnt = ratings.duplicated(subset=["user_id", "movie_id", "rated_at"]).sum()
print("dup_cnt:", dup_cnt)
ratings2 = ratings.drop_duplicates(subset=["user_id", "movie_id", "rated_at"], keep="first").copy()
ratings2["rating_num"] = pd.to_numeric(ratings2["rating"], errors="coerce")
df_full = (
ratings2
.merge(movies, on="movie_id", how="left")
.merge(users, on="user_id", how="left")
)
df_clean = df_full[
(df_full["is_available"] == 1) &
(df_full["review_status"].isin(["OK", "SUSPECT"])) &
(df_full["rating_num"].notna())
].copy()
print("rows:", len(df_clean))
# 정답 코드
1. shape[1] vs len() (가장 큰 실수!)
마지막 출력 부분에서 큰 차이가 있습니다.
- 나: df_clean.shape[1] → 데이터프레임의 '열(Column) 개수'를 출력
- 정답: len(df_clean) 또는 df_clean.shape[0] → 데이터프레임의 '행(Row) 개수'를 출력
- 포인트: "rows:"라고 출력하면서 열 개수를 보여주면 데이터 건수를 확인하려는 의도와 완전히 다른 값이 나온다. 행 개수는 0번 인덱스(shape[0]), 열 개수는 1번 인덱스(shape[1])임을 꼭 기억!!!
2. notna() vs isna() != False
결과는 같을 수 있지만, 가독성과 효율성에서 차이가 난다.
- 나: (df_full['rating_num'].isna() != False)
- 정답: (df_full["rating_num"].notna())
- 포인트: isna() != False는 "결측치니? 아니, 그게 거짓이 아니야(즉, 결측치가 아니야)"라는 이중 부정 형태라 코드를 읽을 때 한 번 더 생각하게 만든다. 앞의 문제와 동일하게 파이썬에서는 존재함을 체크할 때 직관적으로 notna()를 쓰는 것이 훨씬 좋다!
3. parse_dates와 데이터 타입의 안전성
- 날짜 데이터: 정답 코드에서는 read_csv를 할 때 parse_dates=["rated_at"]를 사용했다. 이렇게 하면 rated_at 컬럼이 처음부터 문자열이 아닌 Timestamp(날짜 객체)로 인식되어 날짜 계산이나 중복 체크 시 훨씬 정확합니다.
- .copy()의 활용: 정답 코드의 ratings2 = ...copy() 부분은 원본 데이터프레임의 슬라이스와 원본 사이의 연결 고리를 끊어준다. 이걸 생략하고 ratings_df['rating_num'] = ... 처럼 할당하면 SettingWithCopyWarning이라는 경고 메시지를 만날 확률이 높다!
Q14. 도시×장르 요약 🚀 도전
(Q13에서 만든 df_clean 사용) df_clean 기준으로 city, genre별로 요약 테이블을 만드세요.
- rating_cnt: 행 개수
- avg_rating: 평균(소수 1자리 반올림)
- 정렬: city 오름차순, genre 오름차순
import pandas as pd
movies_df = pd.read_csv("movies.csv")
ratings_df = pd.read_csv("ratings.csv")
users_df = pd.read_csv("users.csv")
ratings_df.drop_duplicates(subset=['user_id', 'movie_id', 'rated_at'], keep="first")
ratings_df.duplicated(subset=['user_id', 'movie_id', 'rated_at']).sum()
ratings_df['rating_num'] = pd.to_numeric('rating', errors="coerce")
df_full = ratings2.merge(movies_df, on="movie_id", how="left")
df_full = df_full.merge(users_df, on="user_id", how="left")
df_clean = df_full[(df_full['is_available'] == 1) & (df_full['review_status'].isin(["OK","SUSPECT"])) & (df_full['rating_num'].isna() != False)]
df_result['genre'] = df_clean.groupby(['city', 'genre'])["rating"].count()
# 내가 작성한 코드
import pandas as pd
users = pd.read_csv("users.csv")
movies = pd.read_csv("movies.csv")
ratings = pd.read_csv("ratings.csv", parse_dates=["rated_at"])
ratings2 = ratings.drop_duplicates(subset=["user_id", "movie_id", "rated_at"], keep="first").copy()
ratings2["rating_num"] = pd.to_numeric(ratings2["rating"], errors="coerce")
df_full = (
ratings2
.merge(movies, on="movie_id", how="left")
.merge(users, on="user_id", how="left")
)
df_clean = df_full[
(df_full["is_available"] == 1) &
(df_full["review_status"].isin(["OK", "SUSPECT"])) &
(df_full["rating_num"].notna())
].copy()
summary = (
df_clean.groupby(["city", "genre"])
.agg(
rating_cnt=("rating_num", "size"),
avg_rating=("rating_num", "mean"),
)
.reset_index()
)
summary["avg_rating"] = summary["avg_rating"].round(1)
summary = summary.sort_values(["city", "genre"], ascending=[True, True])
print(summary)
# 정답 코드
1. inplace를 쓰지 않은 변경은 저장되지 않는다
이 부분이 가장 큰 실수!
- 나: ratings_df.drop_duplicates(...)
- 문제점: 이렇게만 작성하면 중복이 제거된 새로운 결과값만 화면에 던져질 뿐, 정작 다음 줄의 ratings_df는 여전히 중복이 남아있는 원본 상태 그대로이다.
- 해결책: ratings_df = ratings_df.drop_duplicates(...) 처럼 변수에 다시 담거나, inplace=True를 명시해야 한다!
2. .agg() vs 직접 할당의 차이 (집계 방식)
집계 결과를 처리하는 방식에서 정답과 큰 차이가 난다.
- 나: df_result['genre'] = df_clean.groupby(...)["rating"].count()
- 문제점:
- df_result라는 변수가 정의되지 않은 상태에서 컬럼을 만들려고 하면 에러가 난다.
- groupby 결과는 인덱스가 ['city', 'genre']인 시리즈 형태인데, 이를 일반적인 컬럼 할당 방식으로 넣으면 데이터 구조가 꼬이게 된다.
- 해결책: 정답 코드처럼 .agg()를 사용해 여러 집계(count, mean)를 한 번에 수행하고, .reset_index()를 통해 인덱스를 컬럼으로 다시 빼주는 과정이 반드시 필요!
3. 컬럼 참조와 데이터 타입 오류
- 따옴표 주의: pd.to_numeric('rating', ...)은 'rating'이라는 글자 자체를 숫자로 바꾸라는 뜻이 된다. 컬럼을 참조하려면 ratings_df['rating']이라고 써야 한다!
- 집계 대상: 정답은 rating_num으로 집계하지만, 나는 rating으로 집계했다. rating이 문자열이라면 mean(평균) 계산 시 에러가 날 수 있다!
D. 시각화(Matplotlib/Seaborn) (Q15–Q18)
Q15. boxplot 해석 🧰 필수
boxplot(박스플롯)에 대한 설명으로 가장 올바른 것은?
A. 박스는 평균을 의미한다
B. 박스는 사분위수(분포의 일부)를, 수염은 나머지 분포(이상치 제외)를 표현한다
C. 수염은 항상 최소/최대값이다
D. boxplot은 범주형 데이터에만 쓸 수 있다
boxplot에서 박스는 사분위수(quartiles)를 보여주고, 수염은 이상치를 제외한 나머지 분포를 보여준다.
이상치(outliers)는 IQR 기반 규칙으로 따로 점으로 표시될 수 있다.
Q16. x축 라벨 겹침 해결 🧰 필수
날짜 라벨이 겹칠 때 가장 흔한 해결 방법은?
A. plt.xticks(rotation=45) 또는 ax.tick_params(rotation=45)
B. df.reset_index()
C. df.astype(int)
D. plt.legend()
Matplotlib에서 라벨이 겹치면 plt.xticks(rotation=45) 또는 ax.tick_params(..., rotation=45)로 회전시키는 게 일반적이다.
tick label 회전은 tick_params(rotation=...)로 설정할 수 있다.
Q17. 평점 분포 히스토그램 🧰 필수
ratings.csv를 불러온 뒤, 아래 조건에 맞는 평점(rating)의 분포를 히스토그램으로 시각화하세요.
- 데이터 로드
- ratings = pd.read_csv("ratings.csv", parse_dates=["rated_at"]) 권장
- 포함 조건(필터)
- review_status가 "OK" 또는 "SUSPECT"
- rating이 결측치가 아닌 행만
- 중복 제거는 하지 않습니다(그대로 사용)
- 그래프 요구사항
- 히스토그램(histogram) 형태 (seaborn의 histplot 사용 가능)
- 제목/축 라벨 포함
- (권장) plt.tight_layout() 적용, bin = 5 권장
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
ratings = pd.read_csv("ratings.csv", parse_dates=["rated_at"])
sns.histplot(ratings, x= 'rating', bins = 5)
plt.title('Rating Distribution (OK/SUSPECT)')
plt.xlabel('Rating')
plt.ylabel('Count')
plt.tight_layout()
plt.show()
# 내가 작성한 코드
parse_dates=["rated_at"] : 날짜 형태로 파싱한다
조건을 줬어야 하는데 그렇게 하지 못했다,,
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
ratings = pd.read_csv("ratings.csv", parse_dates=["rated_at"])
df = ratings[
ratings["review_status"].isin(["OK", "SUSPECT"]) &
ratings["rating"].notna()
].copy()
plt.figure(figsize=(6, 4))
sns.histplot(data=df, x="rating", bins=5)
plt.title("Rating Distribution (OK/SUSPECT)")
plt.xlabel("Rating")
plt.ylabel("Count")
plt.tight_layout()
plt.show()
# 정답 코드
Q18. 리뷰 상태별 평점 개수 막대그래프 🧰 필수
ratings.csv를 불러온 뒤, review_status별 평점(리뷰) 개수를 막대그래프로 시각화하세요.
요구사항
- 데이터 로드
- ratings = pd.read_csv("ratings.csv")
- (선택) parse_dates=["rated_at"]를 사용해도 OK
- 집계/그래프
- x: review_status
- y: 각 상태의 개수(count)
- seaborn의 countplot 사용 권장 (사전 집계 없이 자동 count)
- 그래프 꾸미기(최소)
- 제목(title), x/y 축 라벨(label) 포함
- plt.tight_layout() 적용
- 다만, 그래프가 보여질 때 왼쪽부터 OK, SUSPECT, BAD 순이어야 한다.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
ratings = pd.read_csv("ratings.csv", parse_dates=["rated_at"])
sns.countplot(data = ratings, x= 'review_status', order=['OK', 'SUSPECT', 'BAD'])
plt.title('Count of Ratings by Review Status')
plt.xlabel('Review Status')
plt.ylabel('Count')
plt.tight_layout()
plt.show()
# 내가 작성한 코드
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
ratings = pd.read_csv("ratings.csv")
plt.figure(figsize=(6, 4))
sns.countplot(data=ratings, x="review_status", order=["OK", "SUSPECT", "BAD"])
plt.title("Count of Ratings by Review Status")
plt.xlabel("Review Status")
plt.ylabel("Count")
plt.tight_layout()
plt.show()
# 정답 코드
기초 프로젝트를 마치고 그동안 배웠던 SQL과 파이썬 전처리/시각화 전반에 대한 성취도 평가를 봤다.
프로젝트 기간 동안 충분히 복습하지 못했던 것도 사실이지만, 생각했던 것보다 AI의 도움 없이는 해결하기 어려운 부분이 많다는 점을 여실히 느끼는 시간이었다.
앞으로는 통계와 머신러닝을 배우게 될 텐데, 너무 AI에만 의존하기보다는 직접 코드를 작성하고 사고하는 데 더 익숙해질 수 있도록 의식적으로 연습해야겠다는 생각이 들었다.
내일부터 다시 마음을 다잡고 달려봐야겠다 🥲🥲
'내일배움캠프 데이터 분석' 카테고리의 다른 글
| 32일차) 내일배움캠프 데이터 분석 TIL - 통계(2) (1) | 2026.02.05 |
|---|---|
| 31일차) 내일배움캠프 데이터 분석 TIL - 통계(1) (0) | 2026.02.04 |
| 27일차) 내일배움캠프 데이터 분석 TIL - 기초 프로젝트(5) (0) | 2026.01.29 |
| 26일차) 내일배움캠프 데이터 분석 TIL - 기초 프로젝트(4) (0) | 2026.01.28 |
| 25일차) 내일배움캠프 데이터 분석 TIL - 기초 프로젝트(3) (0) | 2026.01.27 |
- Total
- Today
- Yesterday
- Til
- 비전공자코딩
- 데이터분석입문
- Tableau
- 파이썬
- 중학생코딩
- 내일배움캠프
- 코딩처음
- 텍스트분석
- 코드카타
- 판다스
- 코딩기초
- 머신러닝
- 통계
- Python
- git
- GoogleColab
- SQL
- 구글코랩
- 태블로
- 데이터분석
- github
- 데이터시각화
- 프로그래밍입문
- 파이썬입문
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 | 29 | 30 |
| 31 |
