每次为Pandas DataFrame获取相同的哈希值

mku*_*kov 22 python pandas

我的目标是为DataFrame获取唯一的哈希值.我从.csv文件中获取它.整点是每次调用hash()时获取相同的哈希值.

我的想法是我创建了这个功能

def _get_array_hash(arr):
    arr_hashable = arr.values
    arr_hashable.flags.writeable = False
    hash_ = hash(arr_hashable.data)
    return hash_
Run Code Online (Sandbox Code Playgroud)

即调用底层numpy数组,将其设置为不可变状态并获取缓冲区的哈希值.

INLINE UPD.

截至2016年11月8日,此版本的功能不再起作用.相反,你应该使用

hash(df.values.tobytes())
Run Code Online (Sandbox Code Playgroud)

请参阅针对numpy数组最有效属性的注释.

内联UPD结束.

它适用于常规pandas数组:

In [12]: data = pd.DataFrame({'A': [0], 'B': [1]})

In [13]: _get_array_hash(data)
Out[13]: -5522125492475424165

In [14]: _get_array_hash(data)
Out[14]: -5522125492475424165 
Run Code Online (Sandbox Code Playgroud)

但后来我尝试将它应用于从.csv文件中获取的DataFrame:

In [15]: fpath = 'foo/bar.csv'

In [16]: data_from_file = pd.read_csv(fpath)

In [17]: _get_array_hash(data_from_file)
Out[17]: 6997017925422497085

In [18]: _get_array_hash(data_from_file)
Out[18]: -7524466731745902730
Run Code Online (Sandbox Code Playgroud)

有人可以解释一下,这怎么可能?

我可以创建新的DataFrame,比如

new_data = pd.DataFrame(data=data_from_file.values, 
            columns=data_from_file.columns, 
            index=data_from_file.index)
Run Code Online (Sandbox Code Playgroud)

它再次有效

In [25]: _get_array_hash(new_data)
Out[25]: -3546154109803008241

In [26]: _get_array_hash(new_data)
Out[26]: -3546154109803008241
Run Code Online (Sandbox Code Playgroud)

但我的目标是在应用程序启动时为数据帧保留相同的哈希值,以便从缓存中检索某些值.

Jon*_*ray 19

由于大熊猫0.20.1的,你可以使用鲜为人知(和不良记录)hash_pandas_object(源代码),并于日前公布pandas.util.它返回数据帧的到达行的一个哈希值(并且也适用于系列等)

import pandas as pd
import numpy as np

np.random.seed(42)
arr = np.random.choice(['foo', 'bar', 42], size=(3,4))
df = pd.DataFrame(arr)

print(df)
#      0    1   2    3
# 0   42  foo  42   42
# 1  foo  foo  42  bar
# 2   42   42  42   42

from pandas.util import hash_pandas_object
h = hash_pandas_object(df)

print(h)
# 0     5559921529589760079
# 1    16825627446701693880
# 2     7171023939017372657
# dtype: uint64
Run Code Online (Sandbox Code Playgroud)

hash_pandas_object(df).sum()如果您想要所有行的整体哈希,您总是可以这样做.

  • 不是100%,但可能`hashlib.sha256(pd.util.hash_pandas_object(df,index = True).values).hexdigest()`将比`.sum()`更少碰撞. (14认同)
  • @mathtick 确实,否则重新排序行会产生相同的哈希值。 (7认同)
  • @GrantCulp `hash_pandas_object` 不会对列名称进行哈希处理:不同列的相同数据将产生相同的哈希值。为了避免这种情况,您可以散列“df.reset_index().T”而不是“df”,或者将“df.columns.values.tobytes()”添加到散列中。 (2认同)

uut*_*uut 10

Joblib提供了针对包含 numpy 数组(例如Pandas数据帧)的对象优化的散列函数。

import joblib
joblib.hash(df)
Run Code Online (Sandbox Code Playgroud)

  • 这对我不起作用!(df1 == df2).all() 为 True,但哈希值不同。 (2认同)
  • @JulianWgs 你有例子吗?为了比较两个系列,如果它们的名称字段不同,它们的哈希值最终会不同,而它们的值相同,但我无法为任何 DataFrame 复制它。 (2认同)

eMM*_*MMe 5

我遇到了类似的问题:检查数据帧是否已更改,我通过散列msgpack序列化字符串来解决它.这在不同的重新加载相同数据之间似乎是稳定的.

import pandas as pd
import hashlib
DATA_FILE = 'data.json'

data1 = pd.read_json(DATA_FILE)
data2 = pd.read_json(DATA_FILE)

assert hashlib.md5(data1.to_msgpack()).hexdigest() == hashlib.md5(data2.to_msgpack()).hexdigest()
assert hashlib.md5(data1.values.tobytes()).hexdigest() != hashlib.md5(data2.values.tobytes()).hexdigest()
Run Code Online (Sandbox Code Playgroud)