내일배움캠프/TIL(Today I Learned)

[2026/03/26] 내일배움캠프 14일차 TIL

sj68 2026. 3. 26. 21:05

오늘은 코드카타를 진행한 뒤 오후부터 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을 작성하며 이번주를 마무리해야겠다.