001
오늘의 키워드: 너무 많아

어제는 Numpy, 오늘은 Pandas. 이틀 연속으로 데이터 분석의 핵심 라이브러리들을 알아보는 시간을 가졌다.
라이브러리... 혹은 패키지... 혹은 모듈 안에 들어있는 속성과 메서드들이 정말 셀 수 없이 많아서, 이걸 하나하나 다 외우는 건 절대 불가능!! 튜터님께서도 함수를 억지로 암기할 필요는 전혀 없고, 필요할 때마다 강의 자료나 구글링을 통해 찾아 쓰면 된다고 말씀해 주셨다. 중요한 건 무작정 외우는 게 아니라, 내가 원하는 결과를 내기 위해 어떤 도구를 어떤 목적으로 꺼내 써야 하는지 그 흐름을 파악하는 것인 듯하다. 😌

002
오늘 학습한 내용
[1] np.array()가 뭔데,
1. np.array가 존재하는 이유
파이썬 기본 내장 기능인 리스트[...]는 수학적 연산 기능이 X
리스트끼리 더하거나 곱하면 숫자가 계산되는 것이 아니라 단순히 리스트 자체가 복사되거나 연결이 됨
리스트끼리의 수학 연산을 좀 더 쉽게 하기 위해 존재하는 것이 넘파이(NumPy) 라이브러리의 np.array라는 것 !
- 일반 리스트 연산: [1, 2, 3] * 2 → [1, 2, 3, 1, 2, 3] (단순 데이터 복사)
- 넘파이 배열 연산: np.array([1, 2, 3]) * 2 → [2, 4, 6] (리스트의 값끼리 서로 곱해짐)
2. ★ 1대1 매칭 연산
기존 파이썬 리스트 구조에서 데이터 여러 개를 서로 계산하려면 for문 같은 반복문을 사용해 원소를 하나씩 꺼내며 연산해야 하는데, 그러면 코드가 참 복잡해진다.
but !! 넘파이 배열은 리스트 값끼리의 연산을 지원.
크기가 같은 배열끼리 연산 명령을 내리면, 넘파이가 내부적으로 각 배열의 동일한 인덱스(위치)에 있는 데이터끼리 자석처럼 1:1로 매칭하여 동시에 계산을 수행한다.
배열A = np.array([10, 20, 30])
배열B = np.array([2, 5, 10])
print(배열A / 배열B)
- 내부 동작: [10/2, 20/5, 30/10]이 동시에 처리됨
- 결과: [5.0, 4.0, 3.0]
굳이 반복문을 돌릴 필요 없이, 배열과 배열의 사칙연산 기호 한 줄만으로 모든 원소의 1:1 매칭 연산이 완결
→ 코드의 가독성 ↑ + 대용량 데이터 처리 속도 빨라짐!!

[2] Pandas 입문
1. Pandas가 뭔가요
파이썬에서 데이터 분석을 위해 사용하는 라이브러리.
엑셀 스프레드시트처럼 표 형태의 데이터를 다룰 수 있고, 전처리와 시각화할 때 거의 필수로 사용한다.
# 터미널
pip install pandas
# 코드블록
!pip install pandas
2. 데이터 구조 2가지
| Series | 1차원 | 인덱스 + 값으로 구성된 하나의 컬럼 |
| DataFrame | 2차원 | 여러 Series가 모인 표. 엑셀 시트랑 동일한 구조 |
# Series 생성 및 조작
ages = pd.Series([25, 30, 35, 28, 32])
ages * 2
ages[ages > 30] # 조건 필터링 ([] 없으면 True/False만 나옴)
sum(ages)/len(ages)
# DataFrame은 딕셔너리 형태로 만드는 게 좋음
df = pd.DataFrame({
'name': ['김철수', '이영희', '박민수'],
'age': [25, 30, 35],
'salary': [3500, 4200, 3800]
})
3. DataFrame 기본 확인 메서드
df.shape # 데이터 크기 (행, 열)
df.columns # 컬럼명 확인
df.dtypes # 각 컬럼 데이터 타입
df.index # 인덱스 정보
df.head() # 상위 5행 (숫자 넣으면 그만큼)
df.tail() # 하위 5행
df.info() # 전체 정보 요약
df.describe() # 기본 통계 정보
▼ 컬럼명 바꾸기
df.columns = ['이름', '나이', '연봉'] # 전체 변경
df.rename(columns={'연봉': '급여'}, inplace=True) # 특정 컬럼만 변경
4. 파일 불러오기
df = pd.read_csv('파일경로/파일명.csv') # CSV
df = pd.read_csv(url변수) # URL 변수로도 가능
df = pd.read_clipboard() # 클립보드에서 붙여넣기 (로컬 전용)
| 구분 | 절대경로 | 상대경로 |
| 기준점 | 컴퓨터 루트 디렉토리 (C:\ 또는 /) | 현재 실행 중인 코드 파일의 위치 (.) |
| 생김새 | C:\Users\...\data.csv (긺) | ./data/data.csv (짧음) |
| 언제 씀? | 내 컴퓨터 안에서만 대충 파일 긁어올 때 | 협업할 때 |
절대경로로 짜면 다른 사람 환경에서 파일이 불러와지지 않으니, 프로젝트할 때는 상대경로로 불러오기
5. 속성 vs 메서드
헷갈리기 쉬운 개념이라 정리함
| 속성 | 괄호 없음. 데이터의 상태/정보를 보여줌 | df.shape, df.columns, df.dtypes |
| 메서드 | 괄호 있음. 데이터에 특정 동작을 수행함 | df.head(), df.info(), df.describe() |
6. 데이터 선택 & 필터링
# 여러 컬럼 선택 (리스트 형태로 넣어야 함!)
df[['Name', 'Age', 'Sex']]
# 조건 필터링
titanic[titanic['Age'] > 30]
# 복합 조건
titanic[(titanic['Sex'] == 'female') & (titanic['Age'] < 30)] # AND
titanic[(titanic['Sex'] == 'female') | (titanic['Age'] < 30)] # OR
# 특정 값 포함 여부
titanic[titanic['Pclass'].isin([1, 2])]
# 결측치 필터링
titanic[titanic['Age'].notna()] # 값 있는 것만
titanic[titanic['Age'].isna()] # 결측치만
7. loc vs iloc 차이
| loc | 행/열 이름(Label) | 포함 |
| iloc | 숫자 위치(Index) | 제외 (파이썬 기본 문법과 동일) |
titanic.loc[0] # 0번 인덱스 행
titanic.iloc[0] # 첫 번째 위치의 행
titanic[titanic['Age'] > 30].loc[0:4] # 조건 + 범위
8. 기타 유용한 것들
# 새 컬럼 추가
titanic['Family_Size'] = titanic['SibSp'] + titanic['Parch'] + 1
# 다중 기준 정렬
titanic.sort_values(['Pclass', 'Age'], ascending=[True, False])
# 인덱스 초기화 / 특정 컬럼을 인덱스로 설정
df.reset_index()
df.set_index('Name')
# 인덱스는 중복값 없는 컬럼(주문번호, 사원번호 등)으로 잡는 게 좋음
003
오늘의 시행착오
반복문과 조건문 제어 (Feat. 개념 다시잡기...)
코드카타 23번
문제 설명
1937년 Collatz란 사람에 의해 제기된 이 추측은, 주어진 수가 1이 될 때까지 다음 작업을 반복하면, 모든 수를 1로 만들 수 있다는 추측입니다. 작업은 다음과 같습니다.
1-1. 입력된 수가 짝수라면 2로 나눕니다.
1-2. 입력된 수가 홀수라면 3을 곱하고 1을 더합니다.
2. 결과로 나온 수에 같은 작업을 1이 될 때까지 반복합니다.
예를 들어, 주어진 수가 6이라면 6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1 이 되어 총 8번 만에 1이 됩니다. 위 작업을 몇 번이나 반복해야 하는지 반환하는 함수, solution을 완성해 주세요. 단, 주어진 수가 1인 경우에는 0을, 작업을 500번 반복할 때까지 1이 되지 않는다면 –1을 반환해 주세요.
.
.
.

문제 자체는 이해함... 어려운 말은 없으니까. 뭘 구하고자 하는지도 알겠음... 근데 내가 생각한 걸 모두 코드로 구현하면 완전 뚱뚱 밤티밤티 코드 될 거 같기도 하고 실행이 잘 될 거라는 자신이 단 1도 없어서 이게 맞나 싶다가... 그냥 해봄.
일단 조건이 만족(주어진 수가 1이 됨)될 때까지 돌아야 하니까 while문을 써야겠다고 생각 (이건 잘했어. 유일하게.)
1차 시도: while문 조건의 오해와 변수 업데이트 누락
# 1차 코드 (실패)
def solution(num):
answer = 0
n = 0
while n == 1: # 문제점 1
if num % 2 == 0:
n = num / 2 # 문제점 2
answer += 1
# ... (생략)
답을 알고 나니까 참 말도 안 되는 코드인 게 보인다.

혼자 고민하다가 (한 3분?ㅋㅋ) 도저히 답이 안 나와서 제미나이한테 물어봤다. 이런 건 계속 째려보고 있는다고 해서 해결 안 된다.

헷갈렸던 부분 & 배운 점
1. while문의 조건식은 '참(True)일 때' 실행된다.
- 오해: 1이 될 때까지 돌려야지! 하고 == 1:로 짬
- 해결: 목표에 도달하기 전까지 돌려야 하므로, != 1 (1이 아닌 동안)을 조건으로 잡아야 함.

2. 이전 단계의 결과물로 다음 단계를 계산하려면 기존 변수를 덮어씌워야 한다.
- 오해: 입력값 num을 보존해야 할 것 같아서 새로운 변수 n에 계산 값을 담음. 이러면 num은 평생 숫자가 안 바뀌어서 무한 루프에 빠진다.
- 해결: 작업 횟수는 answer가 세고 있으니, 숫자가 변경되는 걸 따라가기 위해 num = num / 2 처럼 변수 자체를 업데이트해야 함.
2차 시도: 조건문 순서 꼬임과 횟수 기준 착각
# 2차 코드 (시간 초과)
def solution(num):
answer = 0
while num != 1:
if num % 2 == 0:
num = num / 2
answer += 1
elif num % 2 == 1:
num = num * 3 + 1
answer += 1
elif num == 1: # 문제점 1
answer = 0
elif num == 500: # 문제점 2
answer = -1
헷갈렸던 부분 & 배운 점
1. while num != 1: 안의 if num == 1:은 절대 실행되지 않는다.
- while문 조건 자체에서 1이 아닌 애들만 들여보내 주기 때문에, 내부의 if num == 1은 실행될 일이 없는 죽은 코드. while문 들어가기 전에 answer = 0으로 선언해둬서 굳이 안 적어도 됨.
2. 제한 조건의 주체를 정확히 파악하자 (num vs answer)
- 오해: 500번 반복을 제한해야 하는데 num > 500으로 계산 중인 '숫자' 크기를 제한해버림.(위에 조건들이 다 그래서 헷갈렸음)
- 해결: 횟수를 세고 있는 answer >= 500으로 조건을 고쳐야 함.
3차 시도: 값 변경과 함수의 종료 (return) 시점 오류
# 3차 코드 (기댓값과 다른 뜬금없는 양수 반환)
def solution(num):
answer = 0
while num != 1:
if num % 2 == 0:
num = num / 2
answer += 1
elif num % 2 == 1:
num = num * 3 + 1
answer += 1
elif answer == 500:
answer = -1 # 문제점
헷갈렸던 부분 & 배운 점
- 값만 바꾸면 코드가 멈추지 않고, 변수가 오염된 채 계산이 이어진다...
- 오해: answer가 500이 되면 -1을 내놓고 그대로 루프가 끝날 줄 알았음. 하지만 뜬금없는 양수 값이 반환되는 현상이 발생
- 원인 분석: answer가 500이 되면 -1로 바뀌지만, while문 탈출 X (num은 여전히 1이 아니니까) 다음 바퀴에서는 answer == 500 조건이 거짓이 되어 다시 위의 조건문으로 넘어가 버림... 결국 num 계산 재개하면서 -1이었던 answer가 다시 0, 1, 2...로 증가하며 카운트가 리셋됨. 이 상태로 num이 1이 될 때까지 끝까지 계산한 뒤 탈출하므로 기댓값(-1)과 전혀 다른 뜬금없는 양수가 반환된 것
- 해결: 특정 조건이 만족되었을 때 계산을 즉시 중단하고 싶다면, 변수 값만 바꿀 게 아니라 return -1을 사용해 함수 전체를 그 즉시 종료하고 빠져나와야 함. (그리고 이때 while문 안에 if문을 독립적으로 여러 개 쓸 수 있다는 것도 새로 배움!)
최종 정답 코드 & 회고
def solution(num):
answer = 0
while num != 1:
# 짝수/홀수 계산하는 if문 한 개
if num % 2 == 0:
num = num / 2
answer += 1
elif num % 2 == 1:
num = num * 3 + 1
answer += 1
# 500번째가 되었을 때 탈출하는 if문 한 개 (독립된 if문 2개 사용 가능!)
if answer == 500:
return -1
return answer
while 조건문의 참/거짓 개념, 루프 안에서 변수를 지속해서 업데이트해야 하는 이유, 그리고 return을 활용한 제어문 탈출 타이밍까지 배우게 된 문제였다...하이고 벅차라.주말 보내고 오면 까먹을 거 같은데 ^^ 위에 정리해둔 내용 눈에 익을 정도로 조금씩 봐야겠다. 열심히 쓴 의미가 있도록...

빨리 레벨업하고 전직합시다
'Today I Learned' 카테고리의 다른 글
| [내일배움캠프 QA/QC 6기] TIL #016 ✨데이터 시각화 (with Matplotlib)✨ (1) | 2026.06.02 |
|---|---|
| [내일배움캠프 QA/QC 트랙 6기 본캠프] TIL #015 데이터 전처리 & 시각화 (0) | 2026.06.01 |
| [내일배움캠프 QA/QC 트랙 6기 본캠프] TIL #013 데이터 분석 입문! (0) | 2026.05.28 |
| [내일배움캠프 QA/QC 트랙 6기 본캠프] TIL #012 (0) | 2026.05.27 |
| [내일배움캠프 QA/QC 트랙 6기 본캠프] TIL #011 (1) | 2026.05.26 |