python
판다스 데이터프레임 손쉽게 정렬하기: 초보자를 위한 가이드

판다스 데이터프레임 손쉽게 정렬하기: 초보자를 위한 가이드

MoeNagy Dev

정렬의 기초

데이터 분석에서 정렬의 중요성 이해하기

데이터 분석에서 데이터를 정렬하는 것은 기본적인 작업으로, 데이터를 추가 처리, 시각화 및 의사 결정을 위해 준비하는 과정에서 핵심적인 단계입니다. 정렬을 통해 다음과 같은 작업을 수행할 수 있습니다:

  • 데이터를 논리적이고 의미 있는 방식으로 조직하기
  • 패턴과 추세를 쉽게 확인하기
  • 효율적인 데이터 조회와 검색 수행하기
  • 데이터 분석과 보고를 용이하게 하기
  • 데이터의 전반적인 품질과 유용성 향상하기

판다스에서 sort_values() 메서드 소개

판다스에서 sort_values() 메서드는 데이터프레임을 정렬하는 주요 방법입니다. 이 메서드를 사용하면 하나 이상의 열을 기준으로 데이터프레임을 오름차순 또는 내림차순으로 정렬할 수 있습니다.

import pandas as pd
 
# 샘플 데이터프레임 생성
df = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie', 'David'],
                   'Age': [25, 30, 35, 40],
                   'Score': [85, 92, 78, 88]})
 
# 'Age' 열을 기준으로 데이터프레임 정렬
sorted_df = df.sort_values(by='Age')
print(sorted_df)

출력:

     Name  Age  Score
0  Alice   25     85
1    Bob   30     92
2 Charlie   35     78
3  David   40     88

단일 열로 정렬하기

단일 열을 기준으로 데이터프레임을 정렬하려면 sort_values() 메서드의 by 매개변수에 해당 열의 이름을 전달하면 됩니다.

# 'Score' 열을 오름차순으로 데이터프레임 정렬
sorted_df = df.sort_values(by='Score')
print(sorted_df)

출력:

       Name  Age  Score
2  Charlie   35     78
0    Alice   25     85
3    David   40     88
1      Bob   30     92

여러 열로 정렬하기

여러 열로 데이터프레임을 정렬하려면 by 매개변수에 열 이름의 리스트를 전달하면 됩니다.

# 'Age'를 오름차순으로, 'Score'를 내림차순으로 데이터프레임 정렬
sorted_df = df.sort_values(by=['Age', 'Score'], ascending=[True, False])
print(sorted_df)

출력:

     Name  Age  Score
0  Alice   25     85
1    Bob   30     92
2 Charlie   35     78
3  David   40     88

오름차순과 내림차순으로 정렬하기

오름차순으로 정렬하기

sort_values() 메서드는 기본적으로 데이터프레임을 오름차순으로 정렬합니다. 오름차순으로 정렬하려면 ascending 매개변수를 명시적으로 True로 설정하면 됩니다.

# 'Age'를 오름차순으로 데이터프레임 정렬
sorted_df = df.sort_values(by='Age', ascending=True)
print(sorted_df)

출력:

     Name  Age  Score
0  Alice   25     85
1    Bob   30     92
2 Charlie   35     78
3  David   40     88

내림차순으로 정렬하기

데이터프레임을 내림차순으로 정렬하려면 ascending 매개변수를 False로 설정하면 됩니다.

# 'Age'를 내림차순으로 데이터프레임 정렬
sorted_df = df.sort_values(by='Age', ascending=False)
print(sorted_df)

출력:

     Name  Age  Score
3  David   40     88
2 Charlie   35     78
1    Bob   30     92
0  Alice   25     85

정렬 중 누락값 처리하기

판다스는 정렬 중 누락값(NaN)을 처리하기 위해 na_position 매개변수에 따라 누락값을 정렬된 데이터프레임의 시작 또는 끝에 배치합니다.

# 누락값이 포함된 데이터프레임 생성
df_with_na = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Emily'],
                           'Age': [25, 30, None, 40, 35],
                           'Score': [85, 92, 78, None, 88]})
 
# 'Age'를 기준으로 데이터프레임 정렬하되, 누락값은 시작에 배치
sorted_df = df_with_na.sort_values(by='Age', na_position='first')
print(sorted_df)

출력:

       Name   Age  Score
2  Charlie  None     78
3   David   40.0     NaN
4   Emily   35.0     88
0   Alice   25.0     85
1     Bob   30.0     92

사용자 정의 순서로 정렬하기

미리 정의된 순서에 따라 정렬하기

미리 정의된 값의 순서에 따라 데이터프레임을 정렬할 수 있습니다. 이는 범주형 변수를 기준으로 정렬할 때 특정 순서를 유지하고 싶을 때 유용합니다.

# 범주형 데이터프레임 생성
df = pd.DataFrame({'Category': ['A', 'B', 'C', 'D', 'E']})
 
# 'Category' 열의 사용자 정의 순서 정의
custom_order = ['C', 'A', 'E', 'B', 'D']
 
# 'Category' 열을 사용자 정의 순서로 데이터프레임 정렬
sorted_df = df.sort_values(by='Category', key=lambda x: pd.Categorical(x, categories=custom_order, ordered=True))
print(sorted_df)

출력:

  Category
2       C
0       A
4       E
1       B
3       D

sort_values()key 매개변수 활용

sort_values()key 매개변수를 사용하면 정렬하는 열에 사용자 정의 정렬 함수를 적용할 수 있습니다. 이는 복잡한 정렬 작업을 수행해야 할 때 유용합니다.

# 'Name' 열의 길이를 기준으로 데이터프레임 정렬
sorted_df = df.sort_values(by='Name', key=lambda x: x.str.len())
print(sorted_df)

출력:

     Name  Age  Score
0  Alice   25     85
1    Bob   30     92
2 Charlie   35     78
3  David   40     88

범주형 데이터 정렬하기

판다스에서 범주형 데이터 작업하기

판다스는 범주형 데이터를 다루기 위한 지원을 제공하며, 데이터 정렬 시 유용하게 사용될 수 있습니다. 범주형 데이터는 판다스의 특수한 데이터 유형으로, 범주의 순서와 의미를 보존할 수 있습니다.

# 범주형 데이터프레임 생성
df = pd.DataFrame({'Category': pd.Categorical(['High', 'Low', 'Medium', 'High', 'Low'], ordered=True)})
 
# 'Category' 열을 기준으로 데이터프레임 정렬
sorted_df = df.sort_values(by='Category')
print(sorted_df)

출력: Category 데이터 정렬

카테고리 열을 기준으로 DataFrame을 정렬할 때, Pandas는 기본값이 문자열인 개별 값을 유지하는 순서를 유지합니다.

# 카테고리 데이터가 있는 DataFrame 생성
df = pd.DataFrame({'Category': pd.Categorical(['High', 'Low', 'Medium'], ordered=True)})
 
# 'Category' 열을 기준으로 DataFrame 정렬
sorted_df = df.sort_values(by='Category')
print(sorted_df)

출력:

    Category
1      Low
2    Medium
0     High

카테고리 순서 유지

정렬 중에 특정한 카테고리의 순서를 유지하려면, 카테고리와 그 순서를 만들 때 카테고리를 정의할 수 있습니다.

# 카테고리와 그 순서 정의
categories = ['Low', 'Medium', 'High']
 
# 순서가 정의된 카테고리 데이터가 있는 DataFrame 생성
df = pd.DataFrame({'Category': pd.Categorical(['High', 'Low', 'Medium'], categories=categories, ordered=True)})
 
# 'Category' 열을 기준으로 DataFrame 정렬
sorted_df = df.sort_values(by='Category')
print(sorted_df)

출력:

    Category
1      Low
2    Medium
0     High

날짜 및 시간 열 정렬

Pandas는 날짜 및 시간 열을 기준으로 정렬하는 등 datetime 데이터를 처리하는 데 탁월한 지원을 제공합니다.

# 날짜 데이터가 있는 DataFrame 생성
import datetime
 
df = pd.DataFrame({'Date': [datetime.datetime(2022, 1, 1),
                           datetime.datetime(2022, 3, 15),
                           datetime.datetime(2021, 12, 31),
                           datetime.datetime(2022, 2, 28)]})
 
# 'Date' 열을 기준으로 DataFrame 정렬
sorted_df = df.sort_values(by='Date')
print(sorted_df)

출력:

           Date
2 2021-12-31 00:00:00
0 2022-01-01 00:00:00
3 2022-02-28 00:00:00
1 2022-03-15 00:00:00

날짜 및 시간 열 기준 정렬

'날짜' 및 '시간'을 포함한 여러 날짜 시간 열을 기준으로 DataFrame을 정렬할 수 있습니다.

# 여러 날짜 시간 열이 있는 DataFrame 생성
df = pd.DataFrame({'Date': [datetime.datetime(2022, 1, 1),
                           datetime.datetime(2022, 3, 15),
                           datetime.datetime(2021, 12, 31),
                           datetime.datetime(2022, 2, 28)],
                   'Time': [datetime.time(10, 30),
                           datetime.time(15, 45),
                           datetime.time(9, 0),
                           datetime.time(12, 0)]})
 
# 'Date' 및 'Time'을 기준으로 DataFrame 정렬
sorted_df = df.sort_values(by=['Date', 'Time'])
print(sorted_df)

출력:

           Date     Time
2 2021-12-31 00:00:00  09:00:00
0 2022-01-01 00:00:00  10:30:00
3 2022-02-28 00:00:00  12:00:00
1 2022-03-15 00:00:00  15:45:00

날짜 시간 구성별 정렬

연도, 월, 일, 시간, 분 및 초와 같은 개별 날짜 시간 구성별로 DataFrame을 정렬할 수도 있습니다.

# 'Date' 열의 연도를 기준으로 DataFrame 정렬
sorted_df = df.sort_values(by=pd.to_datetime(df['Date']).dt.year)
print(sorted_df)

출력:

           Date     Time
2 2021-12-31 00:00:00  09:00:00
0 2022-01-01 00:00:00  10:30:00
3 2022-02-28 00:00:00  12:00:00
1 2022-03-15 00:00:00  15:45:00

정렬 성능 최적화

데이터 프레임의 정렬은 계산적으로 비용이 많이 들기 때문에 정렬 데이터의 성능을 고려하는 것이 중요합니다. Pandas는 정렬 성능을 최적화하기 위해 여러 옵션을 제공합니다.

# 새로운 DataFrame을 생성하지 않고 원래의 DataFrame을 재정렬하여 메모리 사용량을 줄임
df.sort_values(by='Age', inplace=True)

sort_values()에서 inplace 매개변수를 사용하면 새로운 DataFrame을 생성하지 않고 원래의 DataFrame을 직접 수정할 수 있습니다. 이는 특히 대용량 데이터셋을 다룰 때 메모리 사용을 더욱 효율적으로 할 수 있습니다.

# 새로운 DataFrame을 생성하지 않고 원래의 DataFrame을 재정렬하여 메모리 사용량을 줄임
df.sort_values(by='Age', inplace=True)

sort_values()에서 ignore_index 매개변수를 사용하면 정렬 후 DataFrame의 원래 인덱스를 무시할 수 있습니다. 이는 원래 인덱스를 유지하지 않아도 되고 메모리를 절약하고자 할 때 유용합니다.

# DataFrame을 정렬하고 원래의 인덱스를 무시
sorted_df = df.sort_values(by='Age', ignore_index=True)

Multi-level 인덱스 정렬

Pandas는 정렬 데이터에서 유용한 Multi-level (계층적) 인덱스를 지원합니다. Multi-level 인덱스를 사용하면 데이터를 보다 복잡한 구조로 정리할 수 있습니다.

Python 튜토리얼 (파트 2)

함수

함수는 Python에서 중요한 개념입니다. 함수를 사용하면 일련의 명령을 캡슐화하고 코드 전체에서 재사용할 수 있습니다. 다음은 직사각형의 넓이를 계산하는 간단한 함수의 예입니다.

def calculate_area(length, width):
    area = length * width
    return area
 
# 함수 호출
rectangle_area = calculate_area(5, 10)
print(rectangle_area)  # 출력: 50

이 예제에서 calculate_area 함수는 lengthwidth라는 두 개의 매개변수를 받고 계산된 넓이를 반환합니다. 이 함수를 다른 값으로 호출하여 다른 직사각형의 넓이를 구할 수 있습니다.

함수는 기본 매개변수 값과 가변 인수를 가질 수도 있습니다.

def greet(name, message="Hello"):
    print(f"{message}, {name}!")
 
greet("Alice")  # 출력: Hello, Alice!
greet("Bob", "Hi")  # 출력: Hi, Bob!
 
def sum_numbers(*args):
    total = 0
    for num in args:
        total += num
    return total
 
print(sum_numbers(1, 2, 3))  # 출력: 6
print(sum_numbers(4, 5, 6, 7, 8))  # 출력: 30

첫 번째 예제에서 greet 함수는 message 매개변수에 대한 기본값을 가지고 있습니다. 두 번째 예제에서 sum_numbers 함수는 임의의 개수의 인수를 받아 해당 값들을 더합니다.

모듈과 패키지

파이썬의 표준 라이브러리는 프로그램에서 사용할 수 있는 다양한 내장 모듈을 제공합니다. 또한 코드를 구성하기 위해 자체 모듈과 패키지를 만들 수도 있습니다.

math 모듈을 사용하는 예제입니다:

import math
 
print(math.pi)  # 출력: 3.141592653589793
print(math.sqrt(16))  # 출력: 4.0

모듈에서 특정 함수나 속성을 가져올 수도 있습니다:

from math import pi, sqrt
 
print(pi)  # 출력: 3.141592653589793
print(sqrt(16))  # 출력: 4.0

자체 모듈을 만들려면 .py 확장자를 가진 Python 파일을 저장하면 됩니다. 예를 들어, my_module.py라는 모듈을 만들어 보겠습니다:

def greet(name):
    print(f"안녕, {name}!")
 
def calculate_area(length, width):
    return length * width

그런 다음 이 모듈의 함수를 메인 스크립트에서 가져와 사용할 수 있습니다:

import my_module
 
my_module.greet("Alice")  # 출력: 안녕, Alice!
area = my_module.calculate_area(5, 10)
print(area)  # 출력: 50

패키지는 모듈을 계층 구조로 구성하는 방법입니다. 패키지를 만들려면 __init__.py 파일이 있는 디렉토리를 생성해야 합니다. 다음은 예시입니다:

my_package/
    __init__.py
    utils/
        __init__.py
        math_functions.py
        string_functions.py
    data/
        __init__.py
        database.py

이 예시에서 my_package는 패키지이며, 두 개의 하위 패키지, utilsdata,를 포함하고 있습니다. 각 하위 패키지에는 패키지 수준의 기능을 정의하는 데 사용할 수 있는 __init__.py 파일이 있습니다.

그런 다음 다음과 같이 하위 모듈에서 함수를 가져와 사용할 수 있습니다:

from my_package.utils.math_functions import calculate_area
from my_package.data.database import connect_to_db
 
area = calculate_area(5, 10)
db_connection = connect_to_db()

객체 지향 프로그래밍 (OOP)

파이썬은 사용자 정의 클래스와 객체를 생성할 수 있는 객체 지향 프로그래밍을 지원합니다. 다음은 간단한 Dog 클래스의 예시입니다:

class Dog:
    def __init__(self, name, breed):
        self.name = name
        self.breed = breed
 
    def bark(self):
        print("멍멍!")
 
# 객체 생성
my_dog = Dog("Buddy", "Labrador")
print(my_dog.name)  # 출력: Buddy
print(my_dog.breed)  # 출력: Labrador
my_dog.bark()  # 출력: 멍멍!

이 예시에서 Dog 클래스에는 객체의 속성을 초기화하는 데 사용되는 __init__ 메서드가 있습니다. bark 메서드는 Dog 객체에서 호출할 수 있는 사용자 정의 메서드입니다.

클래스 간에 상속 관계를 생성할 수도 있습니다:

class GuideDog(Dog):
    def __init__(self, name, breed, training_level):
        super().__init__(name, breed)
        self.training_level = training_level
 
    def guide(self):
        print("주인을 안내하고 있어요!")
 
guide_dog = GuideDog("Buddy", "Labrador", "고급")
guide_dog.bark()  # 출력: 멍멍!
guide_dog.guide()  # 출력: 주인을 안내하고 있어요!

이 예시에서 GuideDog 클래스는 Dog 클래스를 상속하며 training_level 속성과 guide 메서드를 추가합니다.

예외 처리

파이썬은 실행 시 발생하는 오류에 대한 효과적인 예외 처리 메커니즘을 제공합니다. 다음은 ZeroDivisionError를 처리하는 예시입니다:

def divide(a, b):
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        print("오류: 0으로 나눌 수 없습니다.")
        return None
 
print(divide(10, 2))  # 출력: 5.0
print(divide(10, 0))  # 출력: 오류: 0으로 나눌 수 없습니다.

이 예시에서 divide 함수는 try-except 블록을 사용하여 ZeroDivisionError를 잡아내고 graceful하게 처리합니다.

사용자 정의 예외도 생성할 수 있습니다:

class InvalidInputError(Exception):
    pass
 
def calculate_area(length, width):
    if length <= 0 or width <= 0:
        raise InvalidInputError("길이와 너비는 양수여야 합니다.")
    return length * width
 
try:
    area = calculate_area(5, 10)
    print(area)  # 출력: 50
    area = calculate_area(-5, 10)
except InvalidInputError as e:
    print(e)  # 출력: 길이와 너비는 양수여야 합니다.

이 예시에서 calculate_area 함수는 입력값이 유효하지 않은 경우 사용자 정의 InvalidInputError 예외를 발생시킵니다. try-except 블록은 이 예외를 잡아내고 처리합니다.

결론

이 튜토리얼에서는 Python의 여러 가지 중요한 개념에 대해 알아보았습니다. 함수, 모듈 및 패키지, 객체 지향 프로그래밍, 예외 처리 등이 그 중입니다. 이러한 주제는 더 복잡하고 견고한 Python 응용 프로그램을 구축하는 데 필수적입니다. 이해를 확고히 하기 위해 제공된 코드 예제를 실습하고 실험하는 것을 기억해주세요. 즐거운 코딩 하세요!

MoeNagy 개발자