문제 개요
pandas로 데이터 분석을 하다 보면 데이터프레임의 각 열에서 최솟값뿐만 아니라 두 번째로 낮은 값을 찾아야 하는 경우가 있습니다. 예를 들어 다음과 같은 결과를 얻고자 하는 것입니다.
Id 2 Salary 30000 Age 23
즉, Id 열에서는 2, Salary 열에서는 30000, Age 열에서는 23이 각각 두 번째로 낮은 값입니다.
해결 방법
이 문제는 df.apply() 함수와 lambda 표현식을 조합하면 간단하게 해결할 수 있습니다. 단계별로 살펴보겠습니다.
먼저 데이터프레임을 정의합니다.
df.apply()함수 안에 lambda 함수를 생성하고, 변수 x가 모든 열에 접근하도록 설정합니다.lambda 내부에서
x.sort_values().unique()[1]표현식을 사용하고axis=0을 지정하면 각 열의 두 번째로 낮은 값이 반환됩니다.
sort_values()로 값을 오름차순 정렬한 뒤 unique()로 중복을 제거하고, 인덱스 [1]로 두 번째 원소를 선택하는 원리입니다.
result = df.apply(lambda x: x.sort_values().unique()[1], axis=0)
예제 코드
실제 동작을 이해하기 위해 전체 코드를 확인해 보겠습니다.
import pandas as pd
df = pd.DataFrame({'Id':[1,2,3,4,5,6,7,8,9,10],
'Salary':[20000,30000,50000,40000,80000,90000,350000,55000,60000,70000],
'Age': [22,23,24,25,26,25,26,27,25,24]
})
print("DataFrame is:\n",df)
print("Second lowest value of each column is:")
result = df.apply(lambda x: x.sort_values().unique()[1], axis=0)
print(result)실행 결과
DataFrame is: Id Salary Age 0 1 20000 22 1 2 30000 23 2 3 50000 24 3 4 40000 25 4 5 80000 26 5 6 90000 25 6 7 350000 26 7 8 55000 27 8 9 60000 25 9 10 70000 24 Second lowest value of each column is: Id 2 Salary 30000 Age 23 dtype: int64
핵심 포인트 정리
sort_values(): 열의 값들을 오름차순으로 정렬합니다.unique(): 중복된 값을 제거하여 고유한 값만 남깁니다.[1]: 정렬된 고유값 중 인덱스 1, 즉 두 번째로 작은 값을 선택합니다.axis=0: 각 열(세로 방향)에 대해 연산을 수행합니다.
참고로 unique()를 사용하기 때문에 최솟값이 여러 개 중복되어 있더라도 실질적으로 서로 다른 값 기준의 두 번째로 낮은 값이 정확하게 추출됩니다. 만약 중복을 허용한 단순 정렬 기준의 두 번째 값이 필요하다면 x.sort_values().iloc[1]과 같이 nsmallest나 iloc를 활용할 수도 있습니다.