[데이터분석] 부트캠프 TIL

20260119 TIL

myun0506 2026. 1. 19. 21:39

[Today I Learn]

- SQL codekata

- Python codekata

- 데이터 전처리 / 시각화 세션


[SQL codekata]

- 문제 1.

1. 문제 링크: https://leetcode.com/problems/classes-with-at-least-5-students/

2. 정답 코드

select class 
from Courses 
group by class
having count(distinct student) >= 5

 

3. 개선할 점: (student, class) is the primary key for this table 조건이 있으므로 굳이 distinct 사용 안해도 됨. 필요 없는데 굳이 사용할 경우 쿼리 내에서 중복 제거 확인을 하고 임시 메모리 사용을 한다는 점에서 비효율적임 → distinct 제거

select class 
from Courses 
group by class
having count(*) >= 5

 

- 문제 2.

1. 문제 링크: https://leetcode.com/problems/find-followers-count/submissions/1889384296/

2. 정답 코드

select user_id, count(*) as followers_count
from Followers
group by user_id
order by user_id asc

 

- 문제 3.

1. 문제 링크: https://leetcode.com/problems/biggest-single-number/description/

2. 정답 코드

select max(mn.num) as num
from MyNumbers mn
where exists (
    select 1
    from MyNumbers m
    where m.num = mn.num
    group by m.num
    having count(*) = 1
)
select max(mn.num) as num
from MyNumbers mn
where mn.num in (
    select m.num
    from MyNumbers m
    group by m.num
    having count(*) = 1
)
  • MAX() 함수를 사용하면, 만약 조건에 맞는 데이터가 하나도 없을 경우(즉, 서브쿼리 결과가 빈 값일 경우)
    • 집계 함수인 MAX()는 자동으로 NULL을 반환

3. 개선할 점: 두 쿼리 모두 정답을 도출하지만, 사실 이 문제는 서브쿼리를 FROM 절에 사용하면 훨씬 간단하고 빠르게 해결할 수 있음

select max(subquery.num) as num
from (select m.num
    from MyNumbers m
    group by m.num
    having count(*) = 1
) as subquery

[Python codekata] 

- 문제 1.

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/120803?language=python3

2. 정답 코드

def solution(num1, num2):
    if num1>50000 or num1<-50000 or num2>50000 or num2<-50000:
        raise ValueError("-50000~50000 사이의 값만 입력할 수 있습니다") 
    answer = num1 - num2
    return answer
solution = lambda num1, num2: num1 - num2

 

- 문제 2.

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/120807

2. 정답 코드

def solution(num1, num2):
    if num1 == num2:
        return 1
    else:
        return -1

 

3. 개선할 점: 한 줄로 삼항 연산자 사용하면 더 간단하게 작성할 수 있음

def solution(num1, num2):
    return 1 if num1 == num2 else -1
def solution(num1, num2):
    return (num1 == num2) * 2 - 1
  • boolean 값을 이용해서 return 1과 -1을 if 문 사용하지 않고 작성

- 문제 3.

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/120820

2. 정답 코드

def solution(age):
    answer = 2022 - age + 1
    return answer

 

3. 개선할 점: 2022년이라는 특정 연도가 바뀔 때를 대비하여 변수화 하기

def solution(age):
    current_year = 2022
    answer = current_year - age + 1
    return answer

 

- 문제 4.

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/120806

2. 정답 코드

def solution(num1, num2):
    answer = num1/num2*1000
    return int(answer)

 

3. 개선할 점: 

  • 문제점
    • 단순히 int(num1 / num2 * 1000)으로 작성할 경우, 부동 소수점(Floating Point) 연산이 개입됨
    • 컴퓨터는 실수를 2진수로 표현하며, 이 과정에서 무한 소수는 근사치로 저장되기에 **정밀도 손실(Rounding Error)**이 발생함
  • 해결 방안
    • 연산 순서의 중요성: 나눗셈(/)을 먼저 수행하면 즉시 실수형(float)으로 형 변환이 일어남
      • 반면, 곱셈(*)을 먼저 수행하여 분자를 키운 뒤 정수 나눗셈(//)을 수행하면, 모든 연산이 정수 도메인(Integer Domain) 내에서 완결됨
    • 성능적 이점: CPU의 FPU(실수 연산 장치)를 사용하는 것보다 ALU(정수 연산 장치)를 사용하는 것이 일반적으로 사이클 소모가 적으며, int() 캐스팅 오버헤드도 줄일 수 있음
def solution(num1, num2):
    answer = num1*1000//num2
    return answer

 

5. 또다른 정답 코드

def solution(num1, num2):
    import math
    answer = math.trunc(1000*num1/num2)
    return answer
  • math 라이브러리를 불러와서 math.trunc 함수 사용해서 소숫점 자리 제거
  • but, 함수 호출할 때마다 import 하는건 비효율적이므로 import문은 함수 밖으로 빼기
import math
def solution(num1, num2):
    answer = math.trunc(1000*num1/num2)
    return answer

[ 데이터 전처리 / 시각화 2-1 , 2-2 ]

- 인덱싱 핵심: .loc vs .iloc 

- 열 선택 : 필요한 컬럼만 남기기

- 조건 필터링 (불리언 인덱싱) : "결제 완료 + A매장 + 오전"

- 정렬 : "메뉴별 판매수량 TOP"을 뽑을 준비

- 클리닝 기본기 4종 세트

- 결측치 처리 : dropna vs fillna

- 중복 처리: duplicated / drop_duplicates

- 미니 결과물 만들기: "매출 컬럼 추가 + 회의용 테이블 정리"

- 저장: 2회차 결과물을 파일로 남기기 (3회차를 위해 필수)

- 행/열 선택 패턴

- 추천하는 실무 습관 2가지

- 조건 필터링 (불리언 인덱싱) 

- 정렬(sort_values, sort_index)이 필요한 이유

- 클리닝(정제)의 4대 문제

https://myun0506.tistory.com/67

 

결측, 중복 전처리: Pandas Cleaning 정제

[ 데이터 전처리 / 시각화 2-1 , 2-2 ]- 인덱싱 핵심: .loc vs .iloc .loc : 라벨(이름) 기반 (행/열 이름으로 접근) ; label(이름표)행/열의 '이름표'를 기준으로 선택ex) 인덱스가 0,1,2가 아니라 A001,A002 같은

myun0506.tistory.com

 


 

[ 아티클 스터디 ]

https://yozm.wishket.com/magazine/detail/1816/

 

그 데이터는 잘못 해석되었습니다 | 요즘IT

무엇이든 데이터가 있으면 쉽게 결정을 내릴 수 있을 것 같습니다. 하지만 현업에서는 데이터가 있어도 결정을 내리기 어려운 상황들이 있습니다. 특히 데이터를 통한 의사결정을 내릴 때, 가장

yozm.wishket.com

  • 주요 포인트:
    • 생존자 편향의 오류
      • 전체 대상을 기준으로 잡는 것이 중요
    • 심슨의 역설
      • 전체 지표와 그룹을 나눈 지표의 방향성이 다르게 나타나는 상황
      • 사용자를 나눌 수 있는 기준은 다양하기 때문에, 지나치게 작게 나누는 것은 복잡도를 높여 해석하기 어려워짐
      • 특성이 다를 수 있다고 생각하는 성별, 연령대, 기기 타입, 신규/기존 여부 등의 기준들을 미리 정하여, 그 기준으로 지표를 살펴보는 것이 효과적임
    • 상관관계를 통한 성급한 일반화
      • 사람은 연관성을 찾고 연결하는 것에 강점이 있어, 비슷해 보이는 패턴이 있다면 쉽게 일반화하는 경향이 있어서 지표 간의 관계를 파악하여 해석하려는 유혹에 쉽게 빠지게 됨
      • 상관성은 있으나 인과성이 없는 경우는 제 3의 공통 원인이 존재할 가능성이 높음
      • 상관관계를 통한 성급한 일반화의 함정에 빠지지 않기 위해, 사용자의 행동과 심리를 인지적으로 구조화하고 두 지표에 동시에 영향을 줄 공통 원인이 있는지 살펴봐야함
      • 또한, 새로운 구조로 지표 간의 관계를 파악하는 과정이 꼭 필요함
    • 목적에 맞지 않는 지표 선택
      • 정확히 어떤 관점에서 개선할지 목적을 명확히 해야함
      • ex) CTA 버튼 조회 유저수 대비 CTA 버튼 클릭 유저수라는 지표 대신 CTA 버튼 조회수 대비 CTA 버튼 클릭수로 지표 변경
    • 세이건 표준 참고하기!!
      • “특별한 주장에는 특별한 근거가 필요하다 (Extraordinary Claims Require Extraordinary Evidence, ECREE)” - 칼 세이건의 ‘세이건 표준’
실제로 내가 데이터 분석 하는 과정에서 너무나 발생하기 쉬운 오류들이라 찔렸음...
내가 보고자 하는 문제상황이 있을 때 지표를 알맞게 설정하는게 얼마나 중요한 일인지 다시 깨닫게 됨
특히 정해진 문제상황이 있으면 전체상황을 보는 것보다 그 핵심 상황을 보기 위해서 일부 대상을 분석하려고 할 수 있는데
그렇게 되면 실제 상황과 다른 왜곡된 상황으로 이해를 할 수 있다는 걸 깨달으니 굉장히 무섭기도 하고 경각심을 일깨우는 계기가 되었음
또한 상관관계를 통한 성급한 일반화 부분에선 그냥 내 얘기를 하는 것 같았음
어떤 프로젝트에서 무언가를 분석하는 과정에 있으면 더 이를 명확하고, 강력하게 분석을 해야한다는 강박관념에
실제 인과성이 없는 두 이벤트를 인과성이 있다고 성급하게 분석할 수 있고 실제로 내 경험에서도 그런 적이 있었던 것 같음
그래서 더욱이 이 두가지 이벤트와 모두 연결되는 제 3의 공통 원인이 있는지 더 고려해보는 것이 얼마나 중요할지 깨닫게 됨

 

'[데이터분석] 부트캠프 TIL' 카테고리의 다른 글

20260122 TIL  (0) 2026.01.22
20260120 TIL  (0) 2026.01.20
20260116 TIL  (0) 2026.01.16
20260115 TIL  (1) 2026.01.15
20260114 TIL  (1) 2026.01.14