기타/통계, 머신러닝

250624_기초 통계학(상관관계, 기술통계, 추론통계) , SQL 파이썬 코드카타

baektree 2025. 6. 24. 21:57

요약/나만의 인사이트

  • 분산, 표준변차는 변동성을 측정하는 두가지 주요 척도이다.
  • 표준편차는 원래 데이터 값과 동일한 단위로 변환되어 평균으로부터 대략 얼마나 떨어졌는지 확인 할 수 있다. 따라서 분산보다 직관적이라 할 수 있다.
  • 상관관계는 두 변수간의 관계를 측정하는 방법이다.
  • 1, -1에 가까우면 높은 상관관계를 뜻한다.
  • 0에 가까울수록 상관관계가 없음을 말한다.
  • 여러 변수들의 상관관계를 나타내는 것을 다변량 분석이라고 한다.
  • pairplot(두변수간 상관관계 여러개), heatmap(색깔로 표시) 그래프로 표시할 수 있다.

새롭게 알게 된 것

1. 통계의 종류

기술통계  

  • 데이터를 요약하고 설명하는 통계 - 특정 대표값으로 요약
  • 단, 데이터 중 이상치라는게 항상 존재할 수 있으니 이 부분 유념해야 함.
  • 평균, 중앙값, 분산, 표준편차 등을 사용
    • 평균: 모든 데이터 합산 / 데이터 개수
    • 중앙값: 데이터셋을 오름차순으로 정렬했을 때 중앙에 위치한 값, 평균보다 이상치의 영향을 덜 받음.
      • 70, 80, 90, 100의 점수가 있다면 표준편차는 125이다.분산: 데이터 값들이 평균으로부터 얼마나 떨어져 있는지를 나타내는 척도, 데이터의 흩어짐 정도 / 분산이 크면 데이터가 넓게 퍼져 있고, 작으면 데이터가 평균에 가깝게 모여 있음을 의미 / 데이터 값에서 평균을 뺀 값을 제곱한 후 이를 모두 더하고 데이터의 개수로 나눈 것
        •  
        • (70-85)^2+(80-85)^2+(90-85)^2+(100-85)^2 / 5
    • 표준편차: 데이터 값들이 평균에서 얼마나 떨어져 있는지 나타내는 통계적 척도로, 분산의 제곱근을 취하여 계산한다. 값이 클수록 데이터가 평균으로부터 더 넓게 퍼져 있음을 의미한다.

추론통계

    • 표본 데이터를 통해 모집단의 특성을 추정하고 가설을 검정하는 통계 방법
    • 데이터 일부로 데이터 전체를 추정
    • 신뢰구간, 가설검정 등을 사용한다.
      • 신뢰구간: 모집단의 평균이 특정 범위 내에 있을 것이라는 확률을 나타냄. EX 만족도 평균이 75점이고 신뢰구간이 70점에서 80점이라면**, 우리는 95%확률**로 실제 평균 만족도가 이 범위 내에 있다고 말할 수 있다.
      • 가설검정: 모집단에 대한 가설을 검증하기 위해 사용
        • 귀무가설 - 변화가 없다. 효과가 없다. (EX 학습 프로그램이 성적에 영향을 미치지 않는다.)
        • 대립가설 - 변화가 있다. 효과가 있다. (EX 학습 프로그램이 성적에 영향을 미친다.)

2. 범주형 데이터/이진형데이터(ex satisfaction, disatisfaction)

  • 막대그래프 - 개수
  • 히스토그램 - 분포

3. 상관관계 ex) 공부시간이 늘어날수록 시험점수가 늘어난다.

  • 정의:
    • 데이터들끼리 서로 관련이 있는지 확인하는 방법
  • 특징:
    • 두 변수간의 상관관계를 측정
    • 1에 가까워지면 양의 방향으로 상관관계가 있다.
    • -1에 가까워지면 음의 방향으로 상관관계가 있다.
    • 0상관관계가 없음을 의미한다.
    • -0.5나 0.5를 가지면 중간정도의 상관관계를 가진다.
  • 상관관계와 인과관계
    • 상관관계는 두 변수간 관계를 나타내며, 인과관계는 한 변수가 다른 변수에 미치는 영햐을 나타낸다.
    • 인과관계는 원인과 결과를 뜻한다.
  • 다변량분석
    • 여러 변수간의 관계를 분석하는 방법이다.
    • 여러 마케팅 채널의 광고비와 매출 간의 관계 분석

특히 어려웠던 것

SQL - CASE WHEN을 통해 컬럼을 만들어서 JOIN하는 문제

  • CASE WHEN을 통해 컬럼을 만들어서 JOIN하는 문제
    • 문제
      • CAR_RENTAL_COMPANY_CAR 테이블과 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블과 CAR_RENTAL_COMPANY_DISCOUNT_PLAN 테이블에서 자동차 종류가 '트럭'인 자동차의 대여 기록에 대해서 대여 기록 별로 대여 금액(컬럼명: FEE)을 구하여 대여 기록 ID와 대여 금액 리스트를 출력하는 SQL문을 작성해주세요. 결과는 대여 금액을 기준으로 내림차순 정렬하고, 대여 금액이 같은 경우 대여 기록 ID를 기준으로 내림차순 정렬해주세요.
    • 문제 구조화
      • 자동차 종류가 ‘트럭’인 자동자의 대여 기록에 대해
      • 대여기록별로 대여 금액을 구하기
      • 조회는 대여 기록 ID, FEE
      • 정렬은 FEE 내림차순, ID 내림차순
    • 단계별 풀이
    # 자동차 종류가 트럭인 자동차의 대여 아이디, 대여기간, 데일리 요금 구하기
    WITH A AS
    (SELECT H.history_id, -- 대여아이디
    	   DATEDIFF(H.end_date, H.start_date) + 1 as rental_date, -- 대여기간
    	   C.daily_fee -- 데일리 요금
    FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY H 
    JOIN CAR_RENTAL_COMPANY_CAR C 
    ON H.car_id = C.car_id
    WHERE C.car_type = '트럭'  -- 자동차 종류가 트럭인
    ),
    
    # rental_date가 7일이상, 30일이상, 90일이상이라고 case when으로 나누기 (WHY PLAN 테이블과 조인해서 할인률을 알아내기 위함)
    B AS 
    (SELECT history_id,
            rental_date,
            daily_fee,
            CASE WHEN rental_date BETWEEN 7 AND 29 THEN '7일 이상'
                WHEN rental_date BETWEEN 30 AND 89 THEN '30일 이상'
                WHEN rental_date >= 90 THEN '90일 이상' END AS duration
    FROM A),
    # B와 PLAN 테이블 JOIN 해서 할인가 찾아내기 
    C AS
    (SELECT B.history_id,
           B.rental_date,
           B.daily_fee,
           COALESCE(P.discount_rate, 0) AS discount_rate -- 7일 미만 대여한 것은 할인률 0으로 나오게 하기으로 
    FROM B LEFT JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN P
    ON B.duration = P.duration_type AND P.car_type = '트럭' -- 트럭인 것만 필터링에 조건에 넣기 
    )
    #대여 아이디, 할인률 적용된 총 가격 구하기 (이때 할인률 적용되지 않는 0/100은 0임)
    SELECT history_id,
            FLOOR(daily_fee * (1- discount_rate/100) * rental_date) as fee
    FROM C 
    ORDER BY FEE DESC, history_id DESC
    

    • 핵심 포인트
      • 목적은 트럭 대여기록에 한해서, 대여 기간에 따른 할인율을 적용하는 것 만약 할인 적용 미구간이라면 할인률을 0으로 입력하는 것
      • 따라서 join 조건 당시 할인구간(7일이상, 30일이상 ~) 그리고 트럭인 것으로 on절에 조건붙이기
      • 그래야지 트럭의 구간별 적용되는 할인률과 적용되지 않는 경우 할인류이 0이 되게끔 join할 수 있음.
      • 만약 on 절 이후에 where p.car_type = ‘트럭’이라고 썼다면 할인 적용 구간의 할인률만 필터링 되었으므로 할인 적용 미구간은 삭제됨.
    구문 설명
  • 구문 설명
    LEFT JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN P
    ON B.duration = P.duration_type AND P.car_type = '트럭’
    B 테이블의 duration(할인구간) 값과
    p테이블의 duration_type 값이 같고,
    P 테이블에서 car_type = ‘트럭’인 행만 붙인다.

    할인구간이 없는, 즉 7일미만의 대여기록에 대해선 null이면 0으로 할인률을 처리할 수 있게 된다.
    LEFT JOIN ... ON B.duration = P.duration_type
    WHERE P.car_type = '트럭’
    where절에 넣으면 할인 적용이 안되는 컬럼들은 사라진다.
  • 다른사람 풀이
    • 대여 아이디, 차 종류, 데일리 요금, 대여기간, 대여기간에 따른 할인 적용구간을 구함
      • DATEDIFF를 통해 대여 일수를 구함 이 때 +1을 더해 대여시작일을 포함시킴
      • CASE WHEN을 통해 할인적용 구간을 컬럼을 생성함 90일 이상 → 30일 이상 → 7일 이상 을 점진적으로 접근해서 쿼리문을 간결하게 만듦
      • CAR와 HISTORY를 조인함
      • 트럭인 것만 조회함
    • 대여 아이디, 할인률이 적용된 총 요금을 구함
      • 만들어놓은 tb1테이블이 다 나오게 plan테이블과 JOIN함
      • 이때 할인 적용구간(7일, 30일, 90일), 차 종류(트럭)가 같은 컬럼을 기준으로 JOIN 함
      • 최종 요금 = 데일리 요금 * 할인적용 * 대여일수
    WITH tb1 as (
        SELECT h.HISTORY_ID,
        c.CAR_TYPE,
        c.DAILY_FEE,
        DATEDIFF(h.END_DATE, START_DATE) + 1 as 'DAY',
        CASE
            WHEN DATEDIFF(h.END_DATE, START_DATE) + 1 >= 90 THEN '90일 이상'
            WHEN DATEDIFF(h.END_DATE, START_DATE) + 1 >= 30 THEN '30일 이상'
            WHEN DATEDIFF(h.END_DATE, START_DATE) + 1 >= 7 THEN '7일 이상'
            ELSE '7일 미만'
        END AS 'RENT_DAY'
        FROM CAR_RENTAL_COMPANY_CAR c
        JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY h ON h.CAR_ID = c.CAR_ID
        WHERE CAR_TYPE = '트럭'
    
    )
    
    SELECT
    t.HISTORY_ID,
    FLOOR((DAILY_FEE * (100 - IFNULL(p.DISCOUNT_RATE,0))/100) * t.DAY) as 'FEE'
    FROM tb1 t
    LEFT JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN p ON t.CAR_TYPE = p.CAR_TYPE
    AND t.RENT_DAY = p.DURATION_TYPE
    ORDER BY FEE DESC, t.HISTORY_ID DESC
    
     
  • 새롭게 알게 된 사실
    • ON t.CAR_TYPE = p.CAR_TYPE AND t.RENT_DAY = p.DURATION_TYPE ON절에 두가지 조건을 붙일 수 있다.
    • LEFT JOIN ... ON 조건 는 필터링 된 것만 붙이는 것이고 WHERE 조건은 붙이고 나서 거르자 는 것이다.
    • COALESCE(P.discount_rate, 0) 해당컬럼이 NULL이면 0을 채워라
    • 0/100은 0이다. 

 

파이썬 - 약수의 개수를 구해서 개수가 짝수 또는 홀수일 경우 달리 조건을 부여하는 것

    • 문제 : https://school.programmers.co.kr/learn/courses/30/lessons/77884
      • 두 정수 left와 right가 매개변수로 주어집니다. left부터 right까지의 모든 수들 중에서, 약수의 개수가 짝수인 수는 더하고, 약수의 개수가 홀수인 수는 뺀 수를 return 하도록 solution 함수를 완성해주세요.
    • 풀이
#약수 개수만 세기
def solution(left, right):
    total = 0 # 최종 리턴값으로, 누적합을 저장하기 위해 total을 0으로 초기화함.

    for number in range(left, right+1): #number에는 13, 14, 15, 16 17이 하나씩 순회됨.
        count = 0
        for i in range(1, number + 1):  #1부터 13까지 순회
            if number % i == 0:  #13을 1로 나눠서 0이면 (약수이면) count에 1을 누적합하기, 약수가 아니면 if문 실행안하니까 (if문은 참일때만 실행) count +1 안함
                count += 1  #count에는 13의 약수의 개수가 담김

        if count % 2 == 0:   #약수의 개수가 짝수이면 total에 13을 더함
            total += number
        else: #약수의 개수가 홀수이면 total에 number를 뺌
            total -= number

    return total #for문을 다 통과한 뒤 total을 반환함.
    
# solution(13, 17) # 43

'''
1. left부터 right+1까지 순회
2. 약수의 개수를 구하기 - count는 반복문 밖에 정의
3. 약수의 개수 기반으로 최종 반환할 total에 더하고 빼기 '''

 

  • 틀렸던 포인트
    • total = [ ]를 for문 안에다 적어서 순회할 때 마다 total 안의 요소가 누적으로 담기지 않고, 빈 배열로 리셋됨
    • 그래서 total.append(number)는 항상 한개의 숫자만 넣고, 다음 루프에서 그 숫자가 사라짐.
    • 따라서 누적합 저장용 리스트는 반복문(for문) 밖에 있어야 함.
  • 다른 사람의 문제 풀이
#약수 개수만 세기
def solution(left, right):
    total = 0 # 최종 리턴값으로, 누적합을 저장하기 위해 total을 0으로 초기화함.

    for number in range(left, right+1): #number에는 13, 14, 15, 16 17이 하나씩 순회됨.
        count = 0
        for i in range(1, number + 1):  #1부터 13까지 순회
            if number % i == 0:  #13을 1로 나눠서 0이면 (약수이면) count에 1을 누적합하기, 약수가 아니면 if문 실행안하니까 (if문은 참일때만 실행) count +1 안함
                count += 1  #count에는 13의 약수의 개수가 담김

        if count % 2 == 0:   #약수의 개수가 짝수이면 total에 13을 더함
            total += number
        else: #약수의 개수가 홀수이면 total에 number를 뺌
            total -= number

    return total #for문을 다 통과한 뒤 total을 반환함.
    
# solution(13, 17) # 43

'''
1. left부터 right+1까지 순회
2. 약수의 개수를 구하기 - count는 반복문 밖에 정의
3. 약수의 개수 기반으로 최종 반환할 total에 더하고 빼기 '''

다음에 적용해 볼 것

  • 이력서 작성시 주의사항
    1. 어떻게든 데이터와 연결시키기
      1. 임직원 만족도 - 만족하는 영역은 어디일까? → 만족하는 부분, 불만족하는 부분 → 액션플랜
      2. 기념일 선물 만족도 결과 - 운영 → 만족도 조사 결과, 운영적 측면 → 문자알림, 화요일 고정배송일
      3. 피싱 사기 → 피싱 사기 수법을 파악하여 예방책을 전사 공개 → 접근방법, 사기수법(지인사칭, 협박), 피해액등 데이터 목록화 → 접근 방법, 사기 수법, 대응책(ex 링크를 전달하며 가입유도하는 것은 사기, 아는 사람의 메신저로 돈을 요구하거나, 새로운 앱을 가입하길 요구한다면 그 사람에게 직접 전화해서 물어보기, 또는 매니저에게 알리기)
    2. 따라서 데이터분석 직무로 전향한 스토리로 어필하기
    3. 자기소개서 현재 작성 내용보다 더 간결하게!? - 얼마나 더 간결해야 하는 것일까…?!
    4. 프로젝트 세션별로 진행하되 - 내가 관심있는 도메인과 연관성이 있고, 나의 기여 포인트가 많은 부분에 한해서 기록
  • [ ] 통계학 기초 1주차 복습!