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

时间:2015-07-22 15:21:19

标签: 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_

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

INLINE UPD。

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

hash(df.values.tobytes())

查看Most efficient property to hash for numpy array的评论。

END OF INLINE 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 

但后来我尝试将它应用于从.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

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

我可以创建新的DataFrame,比如

new_data = pd.DataFrame(data=data_from_file.values, 
            columns=data_from_file.columns, 
            index=data_from_file.index)

然后再次运作

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

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

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

3 个答案:

答案 0 :(得分:14)

从Pandas 0.20.1开始,您可以使用events: { load: function() { this.update({ chart: { spacingBottom: 50 } }, false); this.redraw(false); } 中最近hash_pandas_object的鲜为人知(并且记录欠佳)pandas.utilssource code)。它返回数据帧的到达行的一个哈希值(也适用于系列等)

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

如果您想要所有行的整体哈希值,则可以随时执行hash_pandas_object(df).sum()

答案 1 :(得分: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()

答案 2 :(得分:0)

Joblib提供了针对包含numpy数组(例如pandas数据帧)的对象优化的哈希函数。

       List<Object> jBeansList = new ArrayList<>();
       DynamicType.Builder<?> classBuilding = null;

        classBuilding = new ByteBuddy().rebase(Custom.class);

    for(MethodsBean method : listMethods ){
       classBuilding = classBuilding.defineMethod(method.getNameGet()
                                                  ,defineTypeProbe(method.getType())
                                                   ,Visibility.PUBLIC)
                                                    .intercept(FixedValue.value(method.getValue()));
    }

    DynamicType.Unloaded<?> classToLoad = classBuilding.make();

    Class<?> jBeanLoaded = classToLoad.load(Main.class.getClassLoader()
                                            ,ClassLoadingStrategy.Default.WRAPPER.opened())
                                             .getLoaded();`