Python 데이터 모니터링: 열 합계 변화 추적 함수
pandas에서 데이터를 처리할 때, merge나 groupby 작업의 오류로 인해 주요 지표의 변화가 간과되기 쉽습니다. det_sum 함수를 소개합니다. 이 함수는 단순히 열의 합계를 계산할 뿐만 아니라 호출 간 편차를 추적하여 ETL 프로세스의 이상을 감지하는 데 도움을 줍니다.
열 합계를 왜 모니터링해야 할까?
데이터 처리에서 주요 지표의 안정성을 추적하는 것은 매우 중요합니다. 예를 들어, 잘못된 키를 사용한 merge 작업은 데이터 양을 예상치 못하게 증가시킬 수 있고, 누락된 값이 있는 groupby는 데이터를 줄일 수 있습니다. 재무 지표는 특히 취약합니다: 매출 합계가 갑자기 15% 변동되면 처리 파이프라인에 문제가 있다는 적신호입니다. df['sales'].sum() 같은 표준 방법은 단순한 숫자만 출력할 뿐 변화 맥락을 제공하지 않고, 각 단계 간 수동 비교를 요구합니다.
det_sum 함수는 이를 자동화하며 다음을 추가합니다:
- 큰 숫자의 자동 포맷팅
- 이전 값과의 비교
- 편리한 테이블 식별
- 사람이 읽기 쉬운 편차 경고
det_sum 함수의 구조
구현은 호출 간 상태를 유지하기 위해 세 개의 전역 변수를 사용합니다:
_previous_sum = None
_case_number = 0
_table_names = {}
함수는 DataFrame과 열 이름을 매개변수로 받습니다. 주요 단계:
- 열 존재 여부 확인
- 현재 합계 계산
- 숫자 포맷팅
- 고유 테이블 코드 이름 생성
- 이전 값과의 비교
코드의 기능과 간결함 사이 균형이 잘 맞습니다:
def det_sum(table, column):
import pandas as pd
import random
global _previous_sum, _case_number, _table_names
_case_number += 1
if column not in table.columns:
print(f"\n🔍 Summary №{_case_number}: Andryukha! The column disappeared '{column}'! Possible crime! Saddle up!")
return
current_sum = table[column].sum()
def format_number(num):
abs_num = abs(num)
if abs_num >= 1_000_000_000:
return f"{num/1_000_000_000:.1f} billion"
elif abs_num >= 1_000_000:
return f"{num/1_000_000:.1f} mln"
elif abs_num >= 1_000:
return f"{num/1_000:.1f} thousand"
else:
return f"{num:.1f}"
formatted_current = format_number(current_sum)
table_id = id(table)
if table_id not in _table_names:
animals = ["Antelope", "Beaver", "Badger", "Wolf", "Otter", "Cheetah", "Gorilla", "Porcupine", "Dolphin",
"Raccoon", "Giraffe", "Zebra", "Hare", "Iguana", "Yemeni chameleon", "Cat", "Kangaroo",
"Lev", "Llama", "Bear", "Walrus", "Rhinoceros", "Deer", "Panda", "Puma",
"Lynx", "Elephant", "Meerkat", "Tiger", "Seal", "Platypus", "Flaamimingo", "Hamster",
"Heron", "Turtle", "Chimpanzee", "Pike", "Emu", "Brambling", "Yak"]
_table_names[table_id] = random.choice(animals)
table_code = _table_names[table_id]
print(f"\n🕵️ Summary AN №{_case_number}: Onservation for object '{table_code}' by column '{column}'")
print("=" * 50)
if _previous_sum is None:
print(f"🔎 Object '{table_animal}' was accepted under observation! Amount: {formatted_current}")
print("📋 Fiksiruem in svodke...")
else:
print(f"💼 Tekuschaya sum: {formatted_current}")
difference = current_sum - _previous_sum
if difference != 0:
formatted_diff = f"{abs(difference):,.0f}".replace(',', ' ')
if difference > 0:
print(f"⬆️ Hmm... Amount wzrosla on {formatted_diff}")
print("🕵️ Looks like, we missed new connection! Sending crew for kontrole!")
else:
print(f"⬇️ Wow! Amount decreased on {formatted_diff}")
print("🔍 Who-then is trying to cover tracks! Need check by cameras!")
else:
print("🤔 Amount not changed...")
print("📝 Zanosim in svodku: Object not outputil, meetings not recorded")
print("=" * 50)
_previous_sum = current_sum
가독성을 위한 숫자 포맷팅
표준 합계 출력의 주요 문제는 큰 숫자의 가독성 저하입니다. format_number 함수는 1500000을 "1.5 mln"으로 변환하여 이를 해결합니다. 알고리즘:
- 10억 이상 값: 10^9로 나누고 소수 첫째 자리 반올림
- 100만 이상: 10^6으로 나누기
- 천 단위: 10^3으로 나누기
- 기타: 소수 첫째 자리 표시
이는 특히 억 단위가 일상인 재무 데이터에서 필수적입니다. 포맷팅은 추가 호출 없이 자동으로 이루어져 분석 속도를 높입니다.
고유 테이블 식별
pandas는 DataFrame 변수 이름을 직접 가져올 수 없으므로, 함수는 메모리 ID(id(table))를 교묘하게 사용합니다. 첫 접근 시 미리 정의된 목록에서 무작위 동물을 선택합니다. 이를 통해:
- 하나의 스크립트에서 여러 테이블 추적
- 테이블별 독립적 변화 이력 유지
- 변환 중 혼란 방지 (소스 테이블 이름이 자주 변경됨)
동물 목록에는 40개 옵션이 있으며, Antelope부터 Yak까지입니다. 동일 테이블의 반복 호출 시 로그 일관성을 위해 저장된 이름을 재사용합니다.
워크플로 통합
지속 사용을 위해 함수를 별도 모듈에 배치하세요. 권장 설정:
- config/func.py 생성
- det_sum 코드 추가
- 메인 스크립트에서 import:
import importlib
import config.func
importlib.reload(config.func)
from config.func import det_sum
importlib.reload을 통한 재로딩은 커널 재시작 없이 변경 사항을 적용합니다. 이 접근법은:
- 코드 중복 감소
- 유틸리티 중앙화
- 메인 스크립트 정리
핵심 포인트
- 상태를 위한 전역 변수: _previous_sum과 _case_number를 사용해 호출 간 변화를 추적하지만, 멀티스레드 환경에서는 주의 필요
- 안전한 검사: 열 존재를 먼저 확인해 처리 중 크래시 방지
- 인간 중심 출력: 숫자 포맷팅과 테마 메시지로 수동 로그 검색 없이 문제 진단 속도 향상
- id()를 통한 식별: 단일 세션 내에서 pandas 우회 방법으로 테이블을 안정적으로 추적
- 유연한 통합: 파이프라인 전체 재설계 없이 필요한 곳에 det_sum 호출 삽입
이 도구는 데이터 변화가 예측 가능해야 하는 복잡한 ETL 프로세스 디버깅에 빛을 발합니다. 구현은 30줄 정도지만 데이터 모니터링의 중요한 공백을 메웁니다.
— Editorial Team
아직 댓글이 없습니다.