[내배캠] 데이터분석 6기/본캠프 기록

[본캠프 19일차] SQL 코드카타, QCC ②, 파이썬 코드카타, 파이썬 공부, 아티클 스터디 ④

물맨두 2025. 3. 14. 21:02

 

후 오늘만 어떻게 버텨보자. (이번 주말에는 주말에도 조금씩 공부해야 할 것 같긴 하지만 아무튼..)

 

오늘 한 일은, 

  • SQL 공부
    • [코드카타] SQL 2문제 풀기 () *오늘 QCC 있으니까 2문제만 풀었음
    • [QCC] 2회차 문제 풀기
      • 문제 풀고 해설 강의까지 참여하기
      • 제출한 쿼리 해설 내용 토대로 회고하기
  • 파이썬 공부
    • [코드카타] 알고리즘 1문제 풀기 (57번)
    • [파이썬 종합반] 4주차, 5주차 수강하기
    • 파이썬 개인 과제 다 풀고 제출하기
  • 네 번째 아티클 스터디 진행 (누적은 19번째(11+4+4))

 

SQL 공부: 2회차 QCC 회고

오늘 QCC 시험장이 저번과 다른 맵이었다. 훨씬 다니기 편해서  좋았다.

(근데 자리에 앉으니까 의자 정중앙에 앉는 게 아니라 왼쪽으로 치우쳐져서 의자에 걸터앉는 게 마음이 불편하긴 했지만)

 

오늘은 문제가 3문제여서 '쉽지 않겠다' 싶었는데, 지난 시험보다 시간이 빠듯했다. 3번까지 다 풀고나니까 한 5분 정도 남아있었다.

1번은 쉽고, 2번과 3번은 좀 어려웠다. 생각을 좀 해야 하는 문제들이었다.

 

아!! 지난 번과 비교해서 오늘은 커서가 계속 튕기는 이슈가 전~~~~~혀 없었다. 문제 푸는 데만 집중할 수 있어서 너무 좋았다.

 

그리고 이번에도 운이 좋게 만점을 받았다! 얏호

내 체감 난이도와는 조금 다르게 맨날 문제는 잘 맞히는 걸 보면 아직 이 정도로 복잡한 정도의 SQL문을 다루는 게 낯선 것 같기도 하고, 또 이것을 SQL문을 사용해서 어떻게 구현해낼지 고민하는 데 많은 시간이 걸리는 듯하다.

 

1. 글로벌 확장 기회 발굴

스파르타㈜의 글로벌 확장 전략을 위해 전년 대비 GNP가 감소한 국가 중 인구가 1천만 명 이상인 국가의 수를 조회해야 합니다.
이전 연도의 GNP 값이 0이거나 NULL인 경우는 제외해주세요.

--2회차 문제1번의 제출 쿼리
SELECT COUNT(Code) country_count
FROM country
WHERE ((GNPOld IS NOT NULL) OR (GNPOld != 0)) AND 
      (GNP < GNPOld) AND 
      (Population >= 10000000)

 

2. 도시개발구역 인구 분석

스파르타㈜의 도시 개발 팀은 각 행정 구역(District) 내 도시들의 평균 인구 수를 분석하고자 합니다. 이를 통해 특정 지역의 성장 가능성을 평가할 수 있습니다.
 - 각 District별 평균 인구(Population)를 계산하세요. 반올림하여 정수로 변환해주세요.
 - 도시가 3개 이상 존재하는 District만 포함해야 합니다.
 - 결과는 평균 인구 수를 기준으로 내림차순 정렬해야 합니다.

-- 2회차 문제2번의 제출 쿼리
SELECT DISTINCT c2.District,
       c2.average_population
FROM (
  SELECT c.District,
         ROUND(AVG(c.Population) OVER (PARTITION BY c.District)) average_population
  FROM (
    SELECT District, 
           Population,
           COUNT(*) OVER (PARTITION BY District) city_cnt
    FROM city
    ) c
  WHERE c.city_cnt >= 3
  ) c2
ORDER BY c2.average_population DESC

 

3. 인기도시 타겟 마케팅

스파르타㈜ 마케팅 팀은 각 대륙에서 인구가 가장 많은 도시를 분석하여 주요 타겟 시장을 선정하고자 합니다.
 - 대륙별 가장 인구가 많은 도시를 찾아야 합니다.
 - 각 대륙별로 인구가 가장 많은 도시를 찾고, 해당 도시만 조회해야 합니다.
 - 도시 정보가 없는 대륙은 제외해주세요.
 - 결과는 인구 기준으로 내림차순 정렬해야 합니다.

--2회차 문제3번의 제출 쿼리
SELECT c.city_name,
       c.country_name,
       c.continent,
       c.population
FROM ((SELECT sc.Name city_name,
             bc.Name country_name,
             bc.continent,
             sc.population,
             MAX(sc.Population) OVER (PARTITION BY bc.continent) population2
      FROM city) sc
  LEFT JOIN 
      (SELECT Code,
              Name, 
              Continent
      FROM country) bc
  ON sc.CountryCode = bc.Code
     ) c
WHERE c.population = c.population2

 

 


 

파이썬 공부①: [코드카타] 알고리즘 문제 풀기 (57번)

57. 모의고사

수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.
 - 1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...
 - 2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...
 - 3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...
1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.
( 가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬 )

def solution(answers):
    answer = []
    
    student1 = [1, 2, 3, 4, 5] #학생들의 문제를 찍는 방식이 반복되는 부분을 리스트로 담아놓음
    student2 = [2, 1, 2, 3, 2, 4, 2, 5]
    student3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]
    
    score = [0, 0, 0] #여기에 학생별로 answers와 일치할 때마다 점수를 기록할 것
    
    for i in range(len(answers)):
        if answers[i] == student1[i % len(student1)]: #정답고 일치하면
            score[0] += 1 #1점 추가
        if answers[i] == student2[i % len(student2)]:
            score[1] += 1
        if answers[i] == student3[i % len(student3)]:
            score[2] += 1
    
    for i in range(len(score)): #최종적으로 score에 담긴 점수를 보는데
        if max(score) == score[i]: #최고점과 해당 점수가 일치하면
            answer.append(i+1) #answer에 해당 학생의 번호(i+1)를 추가함
    return answer

 


 

파이썬 공부②: 파이썬 개인 과제 풀기


🔗 1~4번 풀었던 과정 TIL 보러 가기

🔗 5~6번 풀었던 과정 TIL 보러 가기


문제 7

…좌표값? 이동…위치…?? ……유클리드, 뭐요?

유클리드 거리 공식은 처음 들어봤는데 (x, y) 좌표가 주어지는 거면 그냥 직각 삼각형 빗변 구하는 느낌으로 풀면 되는 걸까…? (이게 뭐야)

 

너무 혼란스럽지만 우선 구글링부터 시도해본다.

[참고] [Python] 파이썬에서 두 점 사이의 거리 계산하기 (유클리드 거리, 맨해튼 거리)

(출처: 위의 참고 벨로그)

 

import math

# 두 점의 좌표
x1, y1 = 1, 2
x2, y2 = 4, 6

# 유클리드 거리 계산
distance = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)

와 진짜였잖아?!

그래서 이동 거리는 제곱근을 구하는 함수 sqrt()를 사용해야 한다고. 아니면 0.5제곱을 해도 된다(그러니까 제곱에서 지수로 2의 역수를 취하면 됨).

그래도 여태까지 math 라이브러리를 사용한 적이 없어서 이번에는 라이브러리를 활용해 코드를 작성해보려 한다.
(추가로 찾아보니, sqrt() 함수는 numpy 라이브러리로도 사용할 수 있다고 한다.)

 

#문제7. 경기 동안 각 선수가 이동한 총 누적 거리를 계산하는 프로그램 구현
from math import sqrt

def calculate_total_distances(player_positions):
    total_distances_message = [] #문제에서 실행 결과로 주어진 형태의 메시지들을 담을 리스트 선언

    for player, total_positions in player_positions.items(): #딕셔너리 형태로 주어지기에 .items() 메소드를 사용해 담긴 요소들을 하나씩 꺼내봄
      total_distances = 0 #거리 계산에 들어가기에 앞서 total_distances 변수를 생성
      for i in range(len(total_positions)-1): #total_positions에 담긴 값들을 사용해 이동 거리를 계산
        x1, y1 = total_positions[i]
        x2, y2 = total_positions[i+1]
        distance = sqrt((x2 - x1)**2+(y2 - y1)**2)
        total_distances += distance #계산한 distance를 total_distances에 더함
      total_distances_message.append(f'{player}의 총 누적 이동 거리: {round(total_distances, 2)} 미터') #총 누적 이동 거리를 계산하면 선수의 이름과 해당 선수의 총 이동 거리를 매치해서 메시지 리스트에 추가함
    
    return total_distances_message

문제가 말을 험하게 해서 그렇지(?) 어려운 문제는 아니었던 것 같다. 

 

문제 8

(르탄이 대체 왜 이러니)

근데 이 문제 전에 코드카타로 풀었던 카카오 문제랑 비슷하다…!


(👇 전에 알고리즘 46번 문제 풀면서 작성한 TIL 보러 가기👇)

 

[본캠프 12일차] ADsP 공부, 데이터 리터러시 공부, 파이썬 코드타카, SQL 코드카타

오늘 한 일은,[ADsP 자격증 챌린지] 6주차 수강하기[데이터 리터러시] 1주차(1-1~1-3) 수강하기파이썬 공부[코드카타] 어제 푼 문제 복습 (42~44번)[코드카타] 파이썬 3문제 풀기 (45~47번)SQL 공부[코드카

maandoo.tistory.com


그땐 영단어만 있었는데 이번엔 한글도 추가된 상황으로 되게 유사하다.
(그나저나 르탄이가 한국어랑 영어만 할 줄 알아서 난 참… 좋다^^)

 

#문제8. 암호 해독 프로그램 구현
#첫 번째로 작성한 코드

def password_decryptor(password_list):
    kor_num = {'영':'0', '일':'1', '이':'2', '삼':'3', '사':'4', '오':'5', '육':'6', '칠':'7', '팔':'8', '구':'9'}
    eng_num = {'zero':'0', 'one':'1', 'two':'2', 'three':'3', 'four':'4', 'five':'5', 'six':'6', 'seven':'7', 'eight':'8', 'nine':'9'}
    password_message = []

    for password in password_list:
      kor_cnt = 0
      eng_cnt = 0
      for kor, num in kor_num.items():
          kor_cnt += password.count(kor)
          password_num = password.replace(kor, num)
      for eng, num in eng_num.items():
          eng_cnt += password.count(eng)
          password_num = password.replace(eng, num)
      password_num = int(password_num)
      password_message.append(f'{password}에 대한 암호는 {password_num}로, 한글은 {kor_cnt}개, 영어는 {eng_cnt}개 입력되었습니다.')
   
    return password_message

전에 풀었던 문제랑 비슷하게 생겨서 금방 풀 줄 알았는데 코드를 작성하면서 아니었음을 깨달았다. 더 어렵잖아, 세상에…

아무튼, 첫 번째로 작성한 코드는 에러가 났다. ValueError가 났다는 걸 보면 내가 원하는 대로 돌아가질 않았다..

17행에서 에러가 났다는데 처음 주어진 암호가 그대로네. 흐아…

 

#문제8. 암호 해독 프로그램 구현
#두 번째로 작성한 코드

def password_decryptor(password_list):
    kor_num = {'영':'0', '일':'1', '이':'2', '삼':'3', '사':'4', '오':'5', '육':'6', '칠':'7', '팔':'8', '구':'9'}
    eng_num = {'zero':'0', 'one':'1', 'two':'2', 'three':'3', 'four':'4', 'five':'5', 'six':'6', 'seven':'7', 'eight':'8', 'nine':'9'}
    password_message = []

    for password in password_list:
      kor_cnt = 0
      eng_cnt = 0
      original_password = password #원래 암호를 original_password로 저장
      for kor, num in kor_num.items():
          kor_cnt += password.count(kor)
          password = password.replace(kor, num) #숫자로 대체한 정보를 아예 password에 반영함
      for eng, num in eng_num.items():
          eng_cnt += password.count(eng)
          password = password.replace(eng, num)
      solved_password = int(password) #마지막에 문자열로 있던 상태를 숫자로 변환
      password_message.append(f'{original_password}에 대한 암호는 {solved_password}로, 한글은 {kor_cnt}개, 영어는 {eng_cnt}개 입력되었습니다.')
   
    return password_message

드디어 코드가 제대로 돌아갔다!

근데 문제는 암호 'zero오six칠'의 경우에 숫자로 변환하면서 숫자 0이 사라지고 567만이 나왔다. (컴퓨터는 바보야..)

 

#문제8. 암호 해독 프로그램 구현
#두 번째로 작성한 코드

def password_decryptor(password_list):
    kor_num = {'영':'0', '일':'1', '이':'2', '삼':'3', '사':'4', '오':'5', '육':'6', '칠':'7', '팔':'8', '구':'9'}
    eng_num = {'zero':'0', 'one':'1', 'two':'2', 'three':'3', 'four':'4', 'five':'5', 'six':'6', 'seven':'7', 'eight':'8', 'nine':'9'}
    password_message = []

    for password in password_list:
      kor_cnt = 0
      eng_cnt = 0
      original_password = password
      for kor, num in kor_num.items():
          kor_cnt += password.count(kor)
          password = password.replace(kor, num)
      for eng, num in eng_num.items():
          eng_cnt += password.count(eng)
          password = password.replace(eng, num)
      solved_password = int(password)
      if len(str(solved_password)) < len(password): #0이 날아가는 것 같다 싶으면 그냥 str 형태로 두기로 함
        solved_password = password
      password_message.append(f'[{original_password}]에 대한 암호는 [{solved_password}]로, 한글은 [{kor_cnt}]개, 영어는 [{eng_cnt}]개 입력되었습니다.')
   
    return password_message

택한 방법은,

  • password(ex. '00146')를 int() 함수로 숫자로 바꿔서 solved_password에 할당한다
  • 이때 str(solved_password)의 길이가 password의 길이보다 짧을 경우에 (ex. '146' < '00146')
  • solved_password를 int() 함수로 변환하지 않는다

고작 택한 방법이 이거라니 눈물이 난다. 그러면 solved_password엔 숫자였다가 문자였다가 이럴 거 아냐. 하…

그치만 데이터 타입을 숫자로 유지하면서 모자란 만큼 앞에 0을 추가해주는 법을 모르겠다.

 

우선 이렇게 두고 나중에 해설 강의 시간이나 아니면 개인적으로라도 물어봐야겠다.

 


문제를 다 풀었으니 제출하기 전에 5번 문제 작성해놓았던 코드가 좀 걸려서 제출 전에 다시 보기로 한다.


(👇 전에 파이썬 개인 과제 5번 풀면서 작성한 TIL 보러 가기👇)

 

[본캠프 17일차] SQL 코드카타, 파이썬 코드카타, 파이썬 공부

오늘 한 일은, SQL 공부[코드카타] SQL 5문제 풀기 (74~78번) 2문제 풀기 (74~75번)파이썬 공부[라이브 세션] 파이썬 2회차 수강하기[코드카타] 알고리즘 1문제 풀기 (55번)[개인 과제] 5~6번 풀기[파이썬

maandoo.tistory.com


#문제5. 이메일 유효성 프로그램
def validate_emails(email_list):
    answer = []
    for email in email_list:
      if '@' not in email:
        answer.append(f'{email} 유효하지 않은 이메일 주소입니다.')
      else:
        id, domain = email.split('@')
        if (len(id) >= 1) and ('.' in domain) and (len(domain) >= 2):
          answer.append(f'{email} 유효한 이메일 주소입니다.')
        else: answer.append(f'{email} 유효하지 않은 이메일 주소입니다.')
    return answer

저 부분에서 domain 부분을 판단하는 코드 부분을 수정하고 싶었다.

 

#문제5. 이메일 유효성 프로그램 (수정한 버전)
def validate_emails(email_list):
    answer = []
    for email in email_list:
      if '@' not in email:
        answer.append(f'{email} 유효하지 않은 이메일 주소입니다.')
      else:
        id, domain = email.split('@')
        d = domain.find('.') #domain에서 '.'의 위치를 변수 d로 지정
        if (len(id) >= 1) and (d != -1) and (d != 0) and (domain[-1] != '.'): #수정한 부분
          answer.append(f'{email} 유효한 이메일 주소입니다.')
        else: answer.append(f'{email} 유효하지 않은 이메일 주소입니다.')
    return answer

결과값은 수정 전과 달라지지 않았는데 도메인( 도메인_이름.확장자 )에서 '.'이 저렇게 중간에 들어있는 경우만 포함되게끔 수정하고 싶었다.

(좌) 수정 전 / (우) 수정 후[현재 코드]

케이스를 더 추가해서 보면 validate_emails() 함수가 이전보다 더 세세하게 판별하고 있음을 알 수 있다.


 

 

 


 

파이썬 공부③: [데이터 분석 파이썬 종합반] 4~5주차 수강하기

패키지(라이브러리)

  • 패키지 : 관련된 여러 개의 모듈을 포함하는 디렉토리
    • 모듈 : 함수들이 뭉쳐진 하나의 .py 파일
    • 디렉토리 ≒ '폴더'

다양한 종류의 패키지

  • pandas : 데이터 조작 및 분석을 위한 라이브러리
  • numpy : 과학적 계산을 위한 라이브러리로, 다차원 배열과 행렬 연산을 지원함 데이터 전처리 할 때 많이 사용하게 될 것
  • matplotlib : 데이터 시각화를 위한 라이브러리로, 여러 그래프와 도표를 생성함
  • seaborn : matplotlib을 기반으로 한 통계용 데이터 시각화 라이브러리로, matplotlib보다 간편하고 아름다운 시각화를 제공함
  • scikit-learn : 머신 러닝 알고리즘을 사용할 수 있는 라이브러리로, 분류, 회귀, 군집화, 차원 축소 등 다양한 머신 러닝 기법을 제공함
  • statsmodels : 통계 분석을 위한 라이브러리로, 회귀 분석, 시계열 분석, 비모수 통계 등 다양한 통계 기법을 제공함
  • scipy : 과학기술 및 수학 연상을 위한 라이브러리로, 선형대수, 최적화, 신호 처리, 통계 분석 등 다양한 기능을 제공함
  • tensorflow : 딥러닝 및 머신 러닝을 위한 오픈소스 라이브러리로, 그래프 기반의 계산을 통해 수치 계산을 수행하고, 신경망을 구축하고 학습할 수 있음 (구글에서 개발)
  • pytorch : 딥러닝을 위한 오픈소스 라이브러리로, 동적 계산 그래프를 사용해 신경망을 구축하고 학습할 수 있음 (페이스북에서 개발)

 

리스트 컴프리헨션 (List Comprehension)

  • 반복문과 조건문을 사용해 하나의 구문으로 만들어 리스트를 보다 간결하게 생성하는 방법 중 하나
# 기본적인 구조
[표현식 for 항목 in iterable if 조건문]

 

리스트 컴프리헨션의 예제

# 예시: 1부터 10까지의 숫자를 제곱한 리스트 생성
squares = [x**2 for x in range(1, 11)]
print(squares)  # 출력: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 예시: 리스트에서 짝수만 선택하여 제곱한 리스트 생성
even_squares = [x**2 for x in range(1, 11) if x % 2 == 0]
print(even_squares)  # 출력: [4, 16, 36, 64, 100]

# 예시: 문자열 리스트에서 각 문자열의 길이를 저장한 리스트 생성
words = ["apple", "banana", "grape", "orange"]
word_lengths = [len(word) for word in words]
print(word_lengths)  # 출력: [5, 6, 5, 6]

# 예시: 리스트 컴프리헨션을 중첩하여 2차원 리스트 생성
matrix = [[i for i in range(1, 4)] for j in range(3)]
print(matrix)  # 출력: [[1, 2, 3], [1, 2, 3], [1, 2, 3]]

 

lambda() 함수

  • 익명 함수로, 이름 없이 정의되는 간단한 함수
  • 한 번만 사용하거나 임시로 필요한 경우에 사용함
  • 간단한 연산이나 조작이 필요한 경우에 lambda() 함수를 이용해 코드를 더 간결하게 작성할 수 있음
  • 데이터 분석의 관점에서는 알아두면 무척 유용한 함수

lambda()의 예제

# 간단한 덧셈 함수
add = lambda x, y: x + y
print(add(3, 5))  # 출력: 8

# 제곱 함수
square = lambda x: x ** 2
print(square(4))  # 출력: 16

# 리스트의 요소 중 짝수만 필터링
# filter(조건 함수, 반복 가능한 데이터)
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # 출력: [2, 4, 6, 8, 10]

# 리스트의 각 요소에 대한 제곱
# map(함수, 반복 가능한 데이터)
numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(lambda x: x ** 2, numbers))
print(squared_numbers)  # 출력: [1, 4, 9, 16, 25]

 

파이썬 에러 대처법

대표적인 에러들

  • SyntaxError (구문 오류) : 코드 문법에 오류가 있음
    • 대처법 : 괄호 열고 닫고 잘했는지, 따옴표 열고 닫고 잘했는지, 콜론을 빼먹진 않았는지 등
  • IndentationError (들여쓰기 오류) : 코드 블록의 들여쓰기가 잘못됨
    • 대처법 : 들여쓰기를 일관적으로 했는지 점검
  • NameError (이름 오류) : 정의되지 않은 변수나 함수를 사용하려고 함
    • 대처법 : 사용하고자 하는 변수/함수를 앞서서 정의했는지, 오탈자 및 대소문자를 틀리지 않았는지 등
  • TypeError (타입 오류) : 데이터 타입이 일치하지 않는 연산이나 함수 호출을 시도함
    • 대처법 : 사용하고자 하는 변수나 함수에 사용하는 데이터 타입을 확인하고 필요한 데이터 타입으로 변환하기 등
  • IndexError (인덱스 오류) : 리스트, 튜플 등에서 존재하는 않는 인덱스에 접근하려고 함
    • 대처법 : 인덱스의 범위 확인하기 등
  • KeyError (키 오류) : 딕셔너리에서 존재하지 않는 키를 사용하려고 함
    • 대처법 : 사용하고자 하는 키가 딕셔너리에 존재하는지 확인하기 등
  • FileNotFoundError (파일을 찾을 수 없음 오류) : 파일을 찾을 수 없음
    • 대처법 : 올바르게 파일 경로를 설정했는지, 해당 파일이 존재하는지 등

 

250314 파이썬 종합반 강의 드디어 다 들었다.. 히야...