(…힘들다 벌써 주말이 지나갔다고? …아직 월요일밖에 안 됐다고오?)
오늘 한 일은,
- SQL 공부
- [코드카타] SQL 5문제 풀기 (64~68번)
- 파이썬 공부
- [라이브 세션] 파이썬 1회차 수강하기
- [코드카타] 파이썬 3문제 풀기 (51~53번)
- [파이썬 종합반] 1주차 수강하기
- 세 번째 아티클 스터디 진행 (누적은 18번째(11+4+3))
아티클 스터디③: 파이썬 초보자가 저지르는 10가지 실수
오늘 읽은 아티클:
파이썬 초보자가 저지르는 10가지 실수 | 요즘IT
파이썬을 처음 배울 때, 우리는 자신도 모르게 몇 개의 나쁜 코딩 습관들을 갖게 됩니다. 처음에는 문제없이 작동했지만, 나중에 정상적으로 작동하지 않거나 뒤늦게 문제를 더 쉽게 해결할 수
yozm.wishket.com
오늘의 아티클은 파이썬 학습 입문자들이 흔히 범하는 나쁜 코딩 습관에 대한 글이다.
아직 뭔 말인지 모르겠는 것도 있고(2️⃣, 4️⃣, 7️⃣… 🔟도 약간은?) 벌써 저지르고 있는 것도 있고(3️⃣, 8️⃣) 의도치 않았으나 잘 지키고 있는 것들도 있다(9️⃣).
3️⃣번의 경우는 프로그래머스의 코드카타 문제들을 풀어서 정답을 맞추면 해당 문제를 푼 다른 사람들의 코드를 볼 수 있는데 그 풀이들에서 자주 본 아이다. 보고서 '저런 것도 있구나' 하고 넘겼다(…). …게을렀던 과거를 반성하며 Numpy가 무엇인지 찾아봤다.
[참고] 파이썬 마스터하기 : Numpy
- NumPy
- 파이썬에서 과학 연산을 위한 기본적인 라이브러리 중 하나.
- "Numeric Python"의 약자로, 대규모 다차원 배열과 행렬 연산에 필요한 다양한 함수와 메소드를 제공.
- C로 구현돼 빠른 속도로 처리함
사실 다른 사람들의 정답 코드를 보면 자주 보이는 것들이 있다. numpy뿐만 아니라 lambda나 enumerate()라든지 하는 것들이다. 저런 것도 자주 쓰인다는 걸 봤으면서도 적극적으로 배우려 하지 않았다. 솔직하게 게을렀던 것 같기도 하고, 왠지 함수를 쓰면 쓸수록 연산 처리가 더 느려지는 거 아닌가 싶기도 했다. 그런데 오늘 아티클 속에서 같은 연산을 단순히 for문으로만 푸는 것과 Numpy를 사용하는 것을 비교해보면 "Numpy가 더 빠르다는 것을 알 수 있습니다. 왜냐하면 Numpy는 작업을 벡터화하기 때문입니다"라고 설명하는 것에서 내가 오해하고 있었음을 알았다.
앞으로 다른 사람들의 정답 코드들을 보면서 모르는 함수나 메소드가 등장하면 그때그때 찾아보고 자주 보이는 방식들은 문제를 풀 때 시도해보려 해야겠다는 생각이 들었다.
[참고] [Python 기본] import 와 From xx import 차이
그리고 서로의 인사이트를 공유할 때 다른 조원분께서 '나쁜 습관 1️⃣의 import *를 지양해야 한다는 점에서 SQL문에서 COUNT(*)를 남용하지 말아야겠단 생각을 했었는데 그 점이 떠올랐고, 데이터 분석 시에 불필요한 범위를 포함시키지 않도록 해야겠다'는 의견에 공감했다.
그래서 아티클 스터디 후 import에 대해서 더 찾아보았다.
- ①import numpy as np (함수 사용 시 : "np.mean()")
- ②from numpy import * (함수 사용 시 : "mean()")
- import * : 와일드 임포트(wild import)라고 함
- 다른 모듈에서 같은 이름 사용 시 충돌이 발생할 수 있음
- ③from numpy import mean (함수 사용 시 : "mean()")
- ②번의 경우에 발생할 수 있는 오류를 사전에 막을 수 있기에 해당 방법을 권장함
- (그러나 공부할 때는 ②이 편하다고)
우선은 ①의 방식대로 써야겠다.
from으로 하면 내장함수 쓰듯이 함수만 입력 가능하다는 것 같은데 그렇게 짧게 써야 하나 싶기도 하고..
SQL 공부: [코드카타] SQL 문제 풀기(64~68번)
64. 헤비 유저가 소유한 장소
이 서비스에서는 공간을 둘 이상 등록한 사람을 "헤비 유저"라고 부릅니다. 헤비 유저가 등록한 공간의 정보를 아이디 순으로 조회하는 SQL문을 작성해주세요.
SELECT *
FROM places
GROUP BY host_id
HAVING COUNT(host_id) >= 2
처음에 작성한 쿼리를 조회했더니 달랑 두 줄만 뜨길래 이건 아니다 싶었다.
공간이 둘 이상 등록한 사람들에 대한 데이터들이 조회되는 거면 해당 host_id에 대해서 최소 2행 이상씩 조회돼서 현재 2개의 host_id가 조회됐으니 그럼 결과 테이블은 최소 4건은 떠야 하는 건데 뭔가 이상하게 조회됐다.
SELECT *
FROM places
WHERE host_id IN (
SELECT host_id
FROM places
GROUP BY host_id --host_id별로 묶어서
HAVING COUNT(host_id) >= 2 --host_id의 개수를 셀 때 2개 이상으로 집계되는 host_id들만 조회해서
) --host_id가 서브쿼리에 조회된 host_id 중 포함되어 있을 때
ORDER BY id
그러면 host_id가 760849인 건이 3건, 30900122인 건이 2건으로 총 5건이 조회된다.
66. 조회수가 가장 많은 중고거래 게시판의 첨부파일 조회하기
USED_GOODS_BOARD와 USED_GOODS_FILE 테이블에서 조회수가 가장 높은 중고거래 게시물에 대한 첨부파일 경로를 조회하는 SQL문을 작성해주세요. 첨부파일 경로는 FILE ID를 기준으로 내림차순 정렬해주세요. 기본적인 파일경로는 /home/grep/src/ 이며, 게시글 ID를 기준으로 디렉토리가 구분되고, 파일이름은 파일 ID, 파일 이름, 파일 확장자로 구성되도록 출력해주세요. 조회수가 가장 높은 게시물은 하나만 존재합니다.
SELECT CONCAT('/home/grep/src/',board_id, '/', file_id, file_name, file_ext) file_path
FROM used_goods_file
WHERE board_id = (
SELECT board_id
FROM used_goods_board
ORDER BY views DESC LIMIT 1
) --used_goods_board 테이블을 views 기준으로 내림차순으로 정렬하여 첫 행만 조회, 이렇게 조회된 board_id와 used_goods_file의 board_id가 일치할 경우만 select절에서 선택하기
처음에 이렇게 쿼리를 작성해서 제출했는데 틀렸다고 해서 하나하나 확인해봤다. used_goods_board 테이블에서 조회수가 가장 많은 게시글의 ID가 B0008이 맞는지, used_goods_file 테이블에서 board_id가 B0008인 파일은 총 몇 건으로 조회되는지, file_path 컬럼에 들어갈 값의 형식이 문제에서 요구하는 대로 적혀졌는지…
'다 맞는데 이상하다'고 생각하면서 다시 문제를 보는데 그제야 문제 속 파묻혀 있는 "첨부파일 경로는 file_id를 기준으로 내림차순 정렬"하라는 조건이 들어왔다. 하… 나는 왜 정렬 조건을 맨날 빠뜨리는 걸까. 해당 조건 반영하여 다음과 같이 쿼리를 수정하니 통과됐다.
SELECT CONCAT('/home/grep/src/',board_id, '/', file_id, file_name, file_ext) file_path
FROM used_goods_file
WHERE board_id = (
SELECT board_id
FROM used_goods_board
ORDER BY views DESC LIMIT 1
)
ORDER BY file_id DESC --file_id 기준으로 내림차순 정렬!^^
68. 저자별 카테고리별 매출액 집계하기
2022년 1월의 도서 판매 데이터를 기준으로 저자 별, 카테고리 별 매출액(TOTAL_SALES = 판매량 * 판매가) 을 구하여, 저자 ID(AUTHOR_ID), 저자명(AUTHOR_NAME), 카테고리(CATEGORY), 매출액(SALES) 리스트를 출력하는 SQL문을 작성해주세요.
결과는 저자 ID를 오름차순으로, 저자 ID가 같다면 카테고리를 내림차순 정렬해주세요
SELECT b.author_id,
a.author_name,
b.category,
b.price*bs.sales_2 total_sales --문제에서 요구한 author_id, author_name, category, total_sales(price*판매량) 조회
FROM (
SELECT book_id,
SUM(sales) sales_2
FROM book_sales
WHERE sales_date LIKE '2022-01%'
GROUP BY book_id
) bs --1)판매일이 2022년 1월인 데이터 중에 book_id별로 sales를 더하여 해당 책이 총 몇 권 팔렸는지 구함
LEFT JOIN book b ON bs.book_id = b.book_id --카테고리, author_id, price 정보를 이용하기 위해 LEFT JOIN하고
LEFT JOIN author a ON b.author_id = a.author_id --author_name 정보를 이용하기 위해 또 LEFT JOIN함
GROUP BY b.author_id, b.category --SELECT절의 total_sales가 저자별, 카테고리별로 연산하도록
ORDER BY b.author_id, b.category DESC --저자 ID를 오름차순으로, 저자 ID가 같다면 카테고리를 내림차순으로
처음에 작성한 쿼리는 이와 같다. 결과 테이블도 조회되는 것 같아서 제출했더니 틀렸다고 했다.
왜 그런지 이리저리 찾아보다가 슬랙 질문방에서 해당 문제에 같은 나와 같은 의문을 갖고 계신 분이 있어서 해당 게시글에 달린 튜터님의 답변을 참고했다.
그러니까 내가 JOIN으로 book_id 컬럼을 기준으로 book_sales 테이블과 book 테이블을 합쳤어도 해당 행 내에서(해당 book_id에 해당하는 price와 sales_2끼리) 곱해서 total_sales를 구하는 게 아니라 랜덤 매칭된다는 무서운 얘기였다. (도대체 왜...)
SELECT b.author_id,
a.author_name,
b.category,
SUM(b.price*bs.sales_2) total_sales --SUM()으로 묶어서 GROUP BY절에 요구한 대로 계산하도록 요구
FROM (
SELECT book_id,
SUM(sales) sales_2
FROM book_sales
WHERE sales_date LIKE '2022-01%'
GROUP BY book_id
) bs
LEFT JOIN book b ON bs.book_id = b.book_id
LEFT JOIN author a ON b.author_id = a.author_id
GROUP BY b.author_id, b.category
ORDER BY b.author_id, b.category DESC
진짜 SUM(b.price*bs.sales_2)로 수정하니까 결과 테이블에 조회되는 값이 달라지면서 이번엔 통과가 됐다. (무서워..)
파이썬 공부①: [코드카타] 알고리즘 문제 풀기(51~53번)
51. 푸드 파이트 대회
(문제 너무 길다. 생략)
def solution(food):
answer = ''
for i in food[1:]: #food 리스트에서 두 번째 값부터 끝까지 반복한다
answer += str(food.index(i)) * (i // 2) #answer에 i의 인덱스를 i를 2로 나눈 몫만큼 반복하여 추가함
answer = answer + '0' + answer[::-1] #최종적으로 answer는 '방금 추가한 answer'+'0'+'answer(거꾸로)'
return answer
이렇게 코드를 실행했는데 테스트 케이스들은 통과했는데 채첨하니 20개 중에 3개에서 실패가 떴다.
이미 이 문제를 위해 코드 하나 짜는 데 머리를 다 썼는지 뭐가 잘못된 건지 모르겠어서 질문방에 바로 해당 문제에 대한 질문을 남겼다.
그러니까 인덱스를 사용할 경우 같은 값이 담겨 있으면 먼저 나오는 것을 계속 취한다는 것인데,
튜터님께서 언급하신 것처럼 food 리스트가 있다고 할 때 food.index(4)라고 하면 계속 2만 나오는 것이고 3은 가져오지 못하는 것이다.
그러니 이런 문제가 있는 index를 사용하기보다 range() 함수를 통해 접근하라고 답변해주셨다.
그래서 다음과 같이 수정하여 정답을 맞췄다.
#최종적으로 제출한 정답 코드
def solution(food):
answer = ''
for i in range(1, len(food)): #range() 함수를 사용해서 누락되는 것 없이 반복하도록 수정
answer += str(i) * (food[i] // 2) #i가 달리 정의됨에 따라 해당 행도 일부 수정
answer = answer + '0' + answer[::-1]
return answer
53. 명예의 전당(1)
(얘도 길어..)
def solution(k, score):
answer = []
memo = []
for i in score:
memo.append(i) #memo에 score의 i값을 추가
memo.sort(reverse=True) #그리고 memo 리스트를 내림차순으로 정렬
memo[:k-1] #그리고서 k번째까지만 memo에서 남기고
answer.append(memo[-1]) #memo의 끝값(=리스트에서 제일 작은 값)을 answer에 추가
return answer
실행한 결괏값을 보니 또 희한하게 연산을 하고 있는 것 같아 중간에 memo[:k-1] 다음 행에 print(memo)를 추가해 실행해봤다.
…?
나는 memo 리스트에서 k개의 값만 남겨놓으라고 했는데 왜 추가되는 족족 다 갖고 있는 거지..?
def solution(k, score):
answer = []
memo = []
for i in score:
memo.append(i)
memo.sort(reverse=True)
memo = memo[:k] #memo를 k개까지만 값들을 갖도록 새로 정의해줌
answer.append(memo[-1])
return answer
혹시나 싶어서 memo = memo[:k]로 다시 정의해주니 memo에 k개의 값만 갖도록 수정됐다.
파이썬 공부②: [데이터 분석 파이썬 종합반] 1주차 수강하기
우선 이 수업은 프로그램 새로 설치 안 해도 돼서 눈물나게(농반~진반~) 좋았다.
Colab 단축키
Shift + Enter | 코드 셀 실행 |
Ctrl + M + A | 새 코드 셀 추가 |
Ctrl + M + D | 코드 셀 삭제 |
Ctrl + M + Z | 실행 취소 |
Ctrl + M + - | 코드 셀 분할 |
Ctrl + M + M | 코드 셀을 마크다운 셀로 변경 |
변수
- 변수 : 값을 저장하는 공간. 사용에 앞서 선언해야 함.
변수의 자료형
- 문자열
- 작은따옴표(' ')나 큰따옴표(" ")로 감싸서 선언
- str1 + str2 : + 연산자를 사용해 서로 다른 문자열들을 연결할 수 있음 주로 파일 경로를 작성할 때 문자열 연산을 사용함
- .upper() 등의 메소드를 사용함
- 숫자열
- 정수(int)나 실수(float) 형태 소수점 이하가 없다→정수형(int) / 소수점 이하가 있다→실수형(float)
- 사칙연산 가능
- 나눗셈에 있어서 //(몫), %(나머지) 연산도 가능 나머지 연산자는 n배수를 사용하고자 할 때 자주 사용함
- abs(), round() 등의 함수를 사용
- 불리언(Boolean)
- 주어진 조건이 참(True) 또는 거짓(False)을 나타내는 데 사용
NaN(Not a Number) NaN은 자료형은 아님. 숫자형 안에 속한 값들 중 하나.
- 데이터에서 결측치(missing value)를 나타내는 특수한 값
- 데이터프레임과 같은 데이터 구조에서는 결측치를 표현할 때 NaN이 사용
- 정의할 수 없는 수치값 (ex. 0으로 나누는 연산, 유효하지 않은 수학적 연산 결과를 나타낼 때
출력문과 입력문
출력문 : print()
- 코드상에 어떤 결과물들을 출 력시켜 사람이 직접 그 결과물을 볼 수 있도록 해줌
- 코드 작성 시 수시로 확인하기 위해, 수정할 에러를 점검하기 위해, 데이터 시각화를 위해 등
입력문 : input()
- 사용자로부터 키보드로 입력을 받는 함수
- 사용자가 숫자를 입력해도 문자열 형태로 입력을 받음
input()으로 숫자를 받더라도 무조건 문자열 형태로 저장되기 때문에 숫자형으로 이용할 것이라면 input()을 int()로 감싸주어야 함
내일은 오늘 주어진 파이썬 개인 과제의 문제들도 확인해서 조금 풀어야겠다.
그리고 코드카타 알고리즘 문제를 많이 풀기보다 우선 일일 2문제로 푸는 양을 줄이고, [파이썬 종합반] 강의를 가능하면 이번 주에 다 끝내겠다는 생각으로 집중적으로 수강해야겠다. 파이썬 라이브 세션도 있고. 코드카타 알고리즘 문제들을 푸는 데 갈수록 시간이 많이 걸려서 앞으로는 우선 하루에 문제를 많이 풀기보다 하나를 풀어도 내가 조금 더 고민해보고 코드에 주석을 달며 기록하는 데 시간을 많이 쏟는 편이 좋을 것 같다.
'[내배캠] 데이터분석 6기 > 본캠프 기록' 카테고리의 다른 글
[본캠프 17일차] SQL 코드카타, 파이썬 코드카타, 파이썬 공부 (0) | 2025.03.12 |
---|---|
[본캠프 16일차] SQL 코드카타, 파이썬 코드카타, 파이썬 공부 (0) | 2025.03.11 |
[본캠프 14일차] SQL 코드카타, 파이썬 코드카타, QCC ①, 데이터 리터러시 공부 (0) | 2025.03.07 |
[본캠프 13일차] 파이썬 코드카타, SQL 코드카타, 데이터 리터러시 공부, 아티클 스터디② (0) | 2025.03.06 |
[본캠프 12일차] ADsP 공부, 데이터 리터러시 공부, 파이썬 코드타카, SQL 코드카타 (0) | 2025.03.05 |