Python 数据监控:跟踪列总和变化的函数
在使用 pandas 处理数据时,很容易因为合并或分组操作中的错误而忽略关键指标的变化。介绍 det_sum 函数,它不仅计算列的总和,还跟踪调用之间的偏差,帮助检测 ETL 过程中的异常。
为什么需要监控列总和?
在数据处理中,跟踪关键指标的稳定性至关重要。例如,使用错误键的合并操作可能会意外膨胀数据量,而包含缺失值的分组操作则会缩小数据量。财务指标尤其脆弱:如果销售额总和突然变化 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
- 值 ≥ 1 千:除以 10^3
- 其他:显示一位小数
这对于财务数据尤为重要,那里数十亿是常态。格式化自动进行,无需额外调用,加速分析过程。
唯一表格标识
由于 pandas 不允许直接获取 DataFrame 变量名,函数使用巧妙技巧:内存 ID (id(table))。首次访问时,从预设列表中随机挑选一个动物名称。这实现了:
- 在一个脚本中跟踪多个表格
- 独立维护每个表格的变化历史
- 避免转换过程中混淆(源表格名称经常变化)
动物列表有 40 个选项,从羚羊到牦牛。同一表格的重复调用会重用保存的名称,确保日志一致性。
集成到工作流
持续使用时,将函数放入单独模块。推荐设置:
- 创建 config/func.py
- 将 det_sum 代码添加到那里
- 在主脚本中导入:
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
暂无评论。