Powrót do strony głównej

Kontrola sumy kolumny w Pythonie | Funkcja Pandas

Artykuł opisuje implementację funkcji det_sum do śledzenia zmian sumy kolumny w pandas. Funkcja automatyzuje monitorowanie danych, formatuje liczby i identyfikuje tabele za pomocą nazw kodowych. Podano przykład kodu i rekomendacje dotyczące integracji z procesem roboczym.

Funkcja det_sum: monitorowanie zmian sumy kolumny w pandas
Advertisement 728x90

# Kontrola danych w Pythonie: funkcja do śledzenia zmian sumy kolumny

Podczas przetwarzania danych w pandas łatwo przeoczyć zmianę kluczowych metryk z powodu błędów w operacjach merge lub groupby. Przedstawiamy funkcję det_sum, która nie tylko oblicza sumę kolumny, ale także rejestruje odchylenia między wywołaniami, pomagając wykrywać anomalie w procesie ETL.

Po co monitorować sumę kolumny?

W procesie przetwarzania danych kluczowe jest śledzenie stabilności najważniejszych wskaźników. Na przykład operacja merge z błędnie podanymi kluczami może niespodziewanie zwiększyć rozmiar danych, a groupby z brakującymi wartościami — go zmniejszyć. Szczególnie narażone są metryki finansowe: jeśli suma sprzedaży nagle zmieni się o 15%, to sygnał alarmowy w potoku przetwarzania. Standardowe podejście z df['sales'].sum() tego nie rozwiązuje — pokazuje surową liczbę bez kontekstu zmian i wymaga ręcznego porównywania między etapami.

Funkcja det_sum automatyzuje ten proces, dodając:

Google AdInline article slot
  • Automatyczne formatowanie dużych liczb
  • Porównanie z poprzednią wartością
  • Wygodną identyfikację tabel
  • Czytelne powiadomienia o odchyleniach

Architektura funkcji det_sum

Implementacja opiera się na trzech zmiennych globalnych do przechowywania stanu między wywołaniami:

_previous_sum = None
_case_number = 0
_table_names = {}

Funkcja przyjmuje dwa parametry: DataFrame i nazwę kolumny. Kluczowe etapy działania:

  • Sprawdzenie istnienia kolumny
  • Obliczenie bieżącej sumy
  • Formatowanie liczby
  • Generowanie unikalnego kodu tabeli
  • Porównanie z poprzednią wartością

Kod funkcji zachowuje równowagę między funkcjonalnością a prostotą:

Google AdInline article slot
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} tys"
        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

Formatowanie liczb dla lepszej czytelności

Główny problem ze standardowym wyświetlaniem sumy to nieczytelność dużych liczb. Funkcja format_number rozwiązuje to, konwertując 1500000 na „1.5 mln”. Algorytm przetwarzania:

  • Dla wartości ≥ 1 mld: dzielenie przez 10^9 z zaokrągleniem do dziesiątych
  • Dla wartości ≥ 1 mln: dzielenie przez 10^6
  • Dla tysięcy: dzielenie przez 10^3
  • Pozostałe — wyświetlanie z jednym miejscem po przecinku

To szczególnie ważne przy pracy z danymi finansowymi, gdzie operacje na miliardach to codzienność. Formatowanie odbywa się automatycznie bez dodatkowych wywołań, co przyspiesza analizę.

Unikalna identyfikacja tabel

Ponieważ w pandas nie da się bezpośrednio pobrać nazwy zmiennej DataFrame, funkcja stosuje sprytny trik — identyfikator pamięci (id(table)). Przy pierwszym obraschenii do tabeli generowane jest losowe zwierzę z predefiniowanej listy. Pozwala to:

Google AdInline article slot
  • Śledzić wiele tabel w jednym skrypcie
  • Zachowywać historię zmian dla każdej tabeli niezależnie
  • Unikać pomyłek przy transformacjach (nazwa oryginalnej tabeli często się zmienia)

Lista zwierząt zawiera 40 wariantów, od Antylopy po Jaka. Przy ponownym wywołaniu dla tej samej tabeli używana jest zapisana nazwa, co zapewnia spójność logów.

Integracja z procesem pracy

Aby używać funkcji na stałe, warto wyodrębnić ją do osobnego modułu. Zalecana struktura:

  • Utworzyć plik config/func.py
  • Umieścić tam kod det_sum
  • Zaimportować w głównym skrypcie:
import importlib

import config.func
importlib.reload(config.func)
from config.func import det_sum

Przeładowanie modułu przez importlib.reload pozwala na wprowadzanie zmian bez restartu kernela. Taki sposób:

  • Zmniejsza duplikację kodu
  • Centralizuje narzędzia
  • Zachowuje czystość głównego skryptu

Co ważne

  • Zmienne globalne jako stan: Użycie _previous_sum i _case_number pozwala śledzić zmiany między wywołaniami, ale wymaga ostrożności w środowiskach wielowątkowych.
  • Bezpieczeństwo sprawdzeń: Funkcja najpierw weryfikuje obecność kolumny, zapobiegając krytycznym błędom w procesie przetwarzania.
  • Wyjście zorientowane na człowieka: Formatowanie liczb i tematyczne komunikaty przyspieszają diagnozę problemów bez ręcznej analizy logów.
  • Identyfikacja przez id(): Metoda omijająca ograniczenia pandas do śledzenia tabel działa stabilnie w ramach jednej sesji wykonania.
  • Elastyczność integracji: Funkcja nie wymaga zmian w istniejących potokach — wystarczy dodać wywołanie det_sum w kluczowych miejscach.

Narzędzie jest szczególnie przydatne przy debugowaniu złożonych procesów ETL, gdzie zmiany danych powinny być przewidywalne. Implementacja zajmuje zaledwie 30 linii kodu, ale zaspokaja kluczową potrzebę monitoringu danych.

— Editorial Team

Advertisement 728x90

Czytaj dalej