You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为Streamlit st.cache_resource的不可哈希DataFrame适配通用哈希函数

针对pandas/polars DataFrame的Streamlit缓存哈希方案

以下是几个兼顾稳定性、唯一性、性能的哈希函数方案,可根据你的DataFrame规模和需求选择:

1. 利用内置校验和(推荐中小规模DataFrame)

Polars和Pandas都有内置的高效校验和计算方式,速度快且能唯一标识DataFrame内容:

Polars 实现

import polars as pl
import streamlit as st

@st.cache_resource(hash_funcs={pl.DataFrame: lambda df: df.checksum()})
def slow_function(df: pl.DataFrame):
    # 你的耗时操作
    ...
  • 优点:Polars的checksum()是内部优化的矢量化计算,速度极快;内容不变则哈希值稳定,页面刷新也不会变;能唯一区分不同内容的DataFrame。
  • 缺点:超大DataFrame(千万级以上行)会有一定计算耗时,但远快于遍历所有单元格。

Pandas 实现

import pandas as pd
import hashlib
import streamlit as st

def pandas_checksum(df: pd.DataFrame):
    # 用hash_pandas_object生成每行的哈希,再聚合为整体哈希
    row_hashes = pd.util.hash_pandas_object(df, index=False)
    return hashlib.sha256(row_hashes.values.tobytes()).hexdigest()

@st.cache_resource(hash_funcs={pd.DataFrame: pandas_checksum})
def slow_function(df: pd.DataFrame):
    # 你的耗时操作
    ...
  • 优点:hash_pandas_object是矢量化操作,比逐单元格哈希快很多;哈希值稳定且唯一。
  • 缺点:同样,超大规模DataFrame会有一定耗时,但在绝大多数场景下足够高效。

2. 采样+元数据哈希(推荐超大DataFrame)

如果你的DataFrame规模极大(亿级行),完全计算校验和也耗时,可以结合元数据+数据采样生成哈希,在性能和唯一性之间做平衡:

import polars as pl
import pandas as pd
import hashlib
import json
import streamlit as st

def large_df_hash(df, sample_size=100):
    combined = {}
    if isinstance(df, pl.DataFrame):
        # 记录元数据:形状、schema
        combined["shape"] = df.shape
        combined["schema"] = df.schema
        # 采样首尾各sample_size行
        combined["head_sample"] = df.head(sample_size).to_dict(as_series=False)
        combined["tail_sample"] = df.tail(sample_size).to_dict(as_series=False)
    elif isinstance(df, pd.DataFrame):
        combined["shape"] = df.shape
        combined["dtypes"] = df.dtypes.astype(str).to_dict()
        combined["head_sample"] = df.head(sample_size).to_dict("records")
        combined["tail_sample"] = df.tail(sample_size).to_dict("records")
    
    # 序列化后哈希
    serialized = json.dumps(combined, sort_keys=True, default=str).encode()
    return hashlib.sha256(serialized).hexdigest()

@st.cache_resource(hash_funcs={pl.DataFrame: large_df_hash, pd.DataFrame: large_df_hash})
def slow_function(df):
    # 你的耗时操作
    ...
  • 优点:采样计算速度极快,几乎不受DataFrame规模影响;元数据+采样能覆盖绝大多数场景的区分需求。
  • 缺点:极端情况下可能出现不同DataFrame哈希碰撞(比如不同数据但采样和元数据完全一致),但概率极低,适合对性能要求极高的场景。

3. Pickle序列化哈希(追求绝对唯一性)

如果需要绝对保证哈希的唯一性(哪怕极端场景),可以将DataFrame序列化后哈希:

import polars as pl
import pandas as pd
import pickle
import hashlib
import streamlit as st

def pickle_based_hash(df):
    # 用最高协议序列化,减少体积提升速度
    pickled_data = pickle.dumps(df, protocol=pickle.HIGHEST_PROTOCOL)
    return hashlib.sha256(pickled_data).hexdigest()

@st.cache_resource(hash_funcs={pl.DataFrame: pickle_based_hash, pd.DataFrame: pickle_based_hash})
def slow_function(df):
    # 你的耗时操作
    ...
  • 优点:能完全唯一标识DataFrame的所有内容,无碰撞风险;哈希值稳定。
  • 缺点:序列化速度比内置校验和慢,且生成的哈希值依赖pickle版本,不同环境如果pickle版本差异可能导致哈希不一致(不过Streamlit环境一般统一)。

内容的提问来源于stack exchange,提问作者Myccha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 22:30:22