오늘은 코드카타를 진행한 뒤 오후부터 pandas 라이브러리에 대해서 학습했다. 새로운 함수들을 사용하기 시작하니 헷갈리는 부분이 많았고 기초를 탄탄하게 다지고 응용 및 문제 풀이를 통해 사고를 확장하는 식으로 학습을 해야겠다.
1) 코드카타
오늘 진행한 코트 카타 문제들은 기존 문제들에서 고민하고 배웠던 내용들을 활용할 수 있어서 생각보다 쉽게 풀렸다. 하지만, 항상 그렇듯이 배울점도 있었다.
1. 핸드폰 번호 가리기

초기 아이디어
1. for 문으로 하나씩 입력받아서 range(:-4)까지 *으로 변환한다
2. 하지만, 이렇게 for문을 이용하면 불필요한 반복이 많아지는데 코드가 비효율적이지 않을까라는 생각이 들었고
3. 전화 번호 뒷 4자리라는 조건을 이용하기로 했다
아이디어
1. 입력받은 phone_number 길이 - 4의 값에 *를 곱해준다
2. 뒷 네자리를 슬라이싱해서 str 끼리 더해준다
def solution(phone_number):
string = phone_number[-4:]
return ('*'*(len(phone_number)-4)+string)

조건을 이용해서 간단하게 코드를 짜니, 실행시간이 0.00ms로 매우 짧았다.
2. 없는 숫자 더하기

초기 아이디어
1. 입력값이 [5,8,4,0,6,7,9] 처럼 순서대로 들어있지 않을 것이기 때문에, sorted()를 통해 정렬된 배열을 만들어준다.
2. if ~ in 을 통해 하나씩 확인해서 없는 숫자를 찾아서 하나씩 sum 해준다.
3. 하지만, 지난번 수학적으로 접근해보자는 생각이 떠올랐고
아이디어
1. 0에서 9까지의 합은 45
2. 45에서 입력받은 정수 배열의 sum을 빼준다
def solution(numbers):
return (45-sum(numbers))
엄청나게 간단한 코드를 작성할 수 있었고 잘 작동했다 !
3. 제일 작은 수 제거하기

아이디어
1. 빈 배열은 조건식에서 False를 반환한다는 것을 저번에 다른 사람의 코드를 보면서 배웠다
2. return A or B를 사용할경우 A가 True일 경우 A를 False일 경우 B를 반환하는 것도 배웠다
3. 저번에 배운 이 두개를 떠올렸고, remove로 min값을 제거해서 배열을 새로 만들어준 뒤
4. 바로 return을 하면 되겠구나 싶었다.
def solution(arr):
answer = arr
answer.remove(min(answer))
return answer or [-1]
새롭게 배운 내용을 활용해서 코드를 깔끔하게 작성하는 것은 정말 즐거운 일이다.
4. 가운데 글자 가져오기

아이디어
1. 짝수, 홀수는 if문으로 판별하고
2. str형태로 반환하니까 두개를 반환할때는 +로 두개의 str을 합치면 되겠고
3. 짝수, 홀수는 if 와 else 두개로 나눌 수 있으므로 삼항 연산자를 사용하자
def solution(s):
return s[len(s)//2] if len(s)%2==1 else s[len(s)//2-1]+s[len(s)//2]
아이디어를 바탕으로 코드를 작성했는데, return 뒤에 너무 많은 내용을 담고 있어 코드가 난잡해보였다.
return str[(len(str)-1)//2 : len(str)//2 + 1]
그래서 다른 사람의 코드를 살펴봤는데, 슬라이싱을 이용한 사례가 있었다. 정말 천재적이라고 생각했는데, 홀수와 짝수의 case를 나누지 않고 슬라이싱의 성질을 이용했기 때문이다.
1. 홀수의 경우 슬라이싱의 시작 위치와 끝 위치가 동일해서 하나의 글자만 return하고
2. 짝수의 경우 슬라이싱의 시작 위치와 끝 위치가 달라져서 두개의 글자를 return했다.
이런 코드 작성법을 다음번에 꼭 써먹어봐야지
5. 음양 더하기

아이디어
1. signs 배열을 검사해서 True, False를 검사하고
2. 같은 index의 absolutes 배열의 값을 바꿔주고
3. sum으로 absolutes 배열의 값을 다 더해준다
def solution(absolutes, signs):
real = absolutes
for x in range(len(signs)):
if signs[x] == False:
real[x] = real[x]*-1
return sum(real)
이렇게 코드를 작성했는데, 나중에 검토해보니 아쉬운점들이 있었다.
1. real 이라는 변수를 굳이 하나 더 정의한 점
2. -real[x]라고 깔끔하고 쓸 수 있는데 real[x]*-1라고 적은 점
3. 또한 == False: 대신 if not 을 사용할 수 있는 점
def solution(absolutes, signs):
for i in range(len(signs)):
if not signs[i]:
absolutes[i] = -absolutes[i]
return sum(absolutes)
아쉬웠던 부분들을 고쳐서 코드를 조금 더 깔끔하게 작성할 수 있었다.
하지만, 다른 사람들의 코드를 보면서 내가 놓치고 있는점을 발견했는데 여러개의 배열을 입력받는 경우에 zip을 써보는 것이 었다.
def solution(absolutes, signs):
return sum(s if sign else -s for s, sign in zip(absolutes, signs))
1. zip을 사용하여 두 배열을 동시에 순회하며 값을 계산하고
2. signs가 True면 양수(s), False면 음수(-s)를 선택하여 합산하도록해서 코드를 더 파이썬답게 만들 수 있었다.
다음번엔 여러 배열을 입력받는 경우에 반드시 zip을 먼저 떠올리고 말겠다.
2) 데이터 분석 세션 복습
데이터 전처리 & 시각화 강의를 듣고 튜터님 세션의 자료를 보면서 panads 사용법을 복습해봤다.
1.필터링
# 샘플 데이터 (품질 검사 결과)
data = {
'공정명': ['A-1', 'B-2', 'C-3', 'D-4'],
'온도': [25.5, 26.1, 24.8, 25.2],
'불량여부': ['정상', '불량', '정상', '정상']
}
df = pd.DataFrame(data, index=['P1', 'P2', 'P3', 'P4'])
df
우선 튜터님의 데이터 분석 입문 1 세션 자료를 기반으로 복습을 해봤다.
기본적으로 loc는 행/열의 이름을 기반으로 데이터에 엑세스하고, iloc은 번호를 기반으로 데이터에 엑세스한다.
df.loc[,] # 에러 발생
df.loc[:,:] # df 그대로 출력
df.loc[:,"온도":] 온도~ 출력
df.loc[:,['공정명','불량여부']] # '공정명','불량여부' column 출력
df.loc["P1"] # P1 row 데이터 출력
df.loc["온도"] # 에러 발생
df.loc["P1":,"온도":] # row, column 동시 필터링
안에 여러가지 데이터 값을 넣어보고 어떤식으로 사용할 수 있는지 체크 해봤다
1. loc[str] 기본적으로 안에 하나만 넣을때는 row 데이터만 가져올 수 있다.
2. 쉼표를 이용해서 앞부분은 row 데이터를 필터링, 뒷 부분은 column 데이터를 필터링 할 수 있다.
3. 배열 형태로 원하는 row나 column들을 골라서 필터링 할 수 있다.
4. 슬라이싱을 이용해서 범위를 지정하여 필터링 할 수 있다.
iloc에 대해서도 동일하게 수행 가능했고
5. iloc의 경우 슬라이싱을할때 [:n]의 경우 n-1까지만 필터링 되는 것을 주의해야했다.
df['온도'] >= 25.0
high_temp = df[df['온도'] >= 25.0]

조건부 필터링의 경우 colum에 조건식을 씌우면, 해당 colum의 데이터가 True, False로 모두 바뀌었고
거기에 한번더 df[]를 씌워주면, 다시 데이터 형태로 True값들만 필터링해서 보여줬다.
isin의 경우에는 필터링하는 용도로도 사용할 수 있었지만, df[]를 씌우지 않고 True, False를 반환받아
데이터 존재 여부를 파악하는데 쓰면 좋을 것 같았다.
# 가상의 반도체 공정 검사 데이터
data = {
'공정ID': ['LOT-01', 'LOT-02', 'LOT-03', 'LOT-04', 'LOT-05'],
'전압': [110, 112, 108, 115, 111],
'습도': [45.2, 50.5, 48.1, 55.3, 46.8],
'판정': ['Pass', 'Pass', 'Fail', 'Pass', 'Fail'],
'담당자': ['김철수', '이영희', '박지민', '김철수', '이영희']
}
df = pd.DataFrame(data)
df.set_index('공정ID', inplace=True) # 공정ID를 인덱스로 설정
df
# 1.인덱스 이름이 'LOT-03'인 데이터의 '습도'와 '판정' 결과만 추출해 보세요.
df.loc['LOT-03',['습도','판정']]
# 2.'판정' 결과가 'Fail'인 데이터들만 골라서 새로운 변수 df_fail에 저장하고 출력해 보세요.
df_fail = df[df['판정'] == 'Fail']
df['df_fail'] = df['판정'] == 'Fail' # 추가적으로 Fail 여부를 나타내는 새로운 colum을 추가해봄
# 3.'전압'이 110 이상이면서 동시에 '담당자'가 '김철수'인 데이터만 필터링해 보세요.
df[(df['전압']>=110) & (df['담당자']=='김철수')]
# 오류 case 괄호 없을 때 / df['전압']>=110 & df['담당자']=='김철수'
간단하게 연습 문제도 풀어봤는데, pandas의 경우 작성 format을 잘 지키는 것이 중요해 보였다.
2. 데이터 가공 및 변형
df['국가'] = 'Korea' # 새로운 colum '국가'를 만들고 'Korea' 데이터를 채워넣음
df['보정전압'] = df['전압'] * 1.1 # 새로운 colum '보정전압'을 만들고 '전압' colum에 연산을 수행후 대입
df = df.drop('국가') # 에러 발생
df = df.drop('국가',axis=0) # 에러 발생
df = df.drop('국가',axis=2) # 에러 발생
df = df.drop('국가',axis=1) # 정상적으로 '국가' colum 삭제
drop 에서 axis의 의미를 파악하기 위해서 여러 시도를 해봤는데, 결국 axis=1만 정상적으로 작동했다.
찾아보니 'Pandas DataFrame에서 axis는 행을 의미하는 0 (또는 'index') 또는 열을 의미하는 1 (또는 'columns')만 허용합니다. '국가' 컬럼을 삭제하려는 것이므로 axis=1를 사용해야합니다'라고 한다.
df.isnull() # True, False로 데이터값들이 다 바뀜
df.isnull().sum() # 컬럼별 결측치 개수 합계를 해주는데, True의 개수를 세는 것으로 보임
df.dropna() # 결측치 모두 제거
df.fillna() # 결측치에 값 채우기
isnull 또한 기본적으로 True, False를 반환했고 .sum()은 True의 개수를 세서 데이터화 해주는 구조였다.
df.fillna의 경우 주로 어떤 데이터 값을 채워 넣는지 궁금했는데
| 평균 (Mean) | 데이터 분포가 정규 분포와 비슷하고, 결측치가 무작위로 발생했다고 가정할 수 있을 때 주로 사용 |
| 중앙값 (Median) | 데이터에 이상치가 많거나 분포가 한쪽으로 치우쳐져(skewed) 있을 때 다고 가정할 수 있을 때 주로 사용 |
| 최빈값 (Mode) | 숫자형 데이터라도 특정 값이 자주 나타나는 경우(예: 평점, 등급 등)에 사용 |
| 이전 값/다음 값 | 결측치 발생 시점 전후의 데이터가 유의미한 정보를 담고 있다고 가정할 때 사용 |
숫자형 데이터의 경우 위와 같은 상황에 따라 각각 사용한다고 한다.
df['column'].fillna(df['column'].mean()) # 평균값으로 채우기
df['column'].fillna(df['column'].median()) # 중앙값으로 채우기
df['column'].fillna(df['column'].mode()[0]) # 최빈값으로 채우기 / 결과가 Series라 [0] 필요
df['colum'].ffill() #(이전 값으로 채우기)
df['colum'].bfill() # (다음 값으로 채우기)
이런식으로 각기 다른 함수를 써서 채워넣을 수 있었다.
데이터 분석의 경우 분량이 많아서 내일 마저 전체적인 내용을 체계적으로 복습해보고 TIL을 작성하며 이번주를 마무리해야겠다.
'내일배움캠프 > TIL(Today I Learned)' 카테고리의 다른 글
| [2026/03/25] 내일배움캠프 13일차 TIL (0) | 2026.03.25 |
|---|---|
| [2026/03/24] 내일배움캠프 12일차 TIL (0) | 2026.03.24 |
| [2026/03/23] 내일배움캠프 11일차 TIL (0) | 2026.03.23 |
| [2026/03/20] 내일배움캠프 10일차 TIL (0) | 2026.03.20 |
| [2026/03/19] 내일배움캠프 9일차 TIL (0) | 2026.03.19 |