дайджест индекса pandas

#python #pandas #digest

#python #pandas #дайджест

Вопрос:

Я хотел бы эффективно вычислить дайджест фрейма данных Pandas, который однозначно и воспроизводимо идентифицирует его содержимое (для целей управления версиями). Предположим, что на данный момент я не беспокоюсь о порядке следования, dtypes, типах индекса и столбцах. Также предположим, что и индекс, и столбцы уже отсортированы monotonic_increasing .

Со значениями все идет достаточно хорошо (опять же, для упрощения, предположим np.float64 ). Но у меня возникли проблемы с индексом (и столбцами), и я не получаю согласованный дайджест. Конечно, я могу делать такие вещи, как преобразование индекса в строку, а затем байты utf-8, но это медленно.

Вот упрощенный пример:

 import hashlib
def pd_val_sha1(df):
    x = df.values
    if not x.flags.c_contiguous:
        x = x.copy(order='C')
    return hashlib.sha1(x).hexdigest()
  

Тест:

 import pandas as pd
import io

str = """s,e,id,x,y,z
2012-01-01,2013-01-01,b,NaN,2,3
2015-10-27,2015-11-03,a,0.04,12.7,NaN
2015-11-15,2016-01-01,a,7.3,-1.2,8
"""
df = pd.read_csv(io.StringIO(str), parse_dates=[0,1], index_col=[0,1,2]).sort_index()
df
  

Out:

                             x     y    z
s          e          id                 
2012-01-01 2013-01-01 b    NaN   2.0  3.0
2015-10-27 2015-11-03 a   0.04  12.7  NaN
2015-11-15 2016-01-01 a   7.30  -1.2  8.0
  

SHA-1 значений:

 pd_val_sha1(df)
>>> 'a7f0335988a967606bd030864e0e30ce03f32ec9'

pd_val_sha1(df.head())
>>> 'a7f0335988a967606bd030864e0e30ce03f32ec9'

pd_val_sha1(pd.concat([df.ix[0:2], df.ix[2:3]]))
>>> 'a7f0335988a967606bd030864e0e30ce03f32ec9'
  

Пока все хорошо. Но когда дело доходит до индекса:

 pd_val_sha1(df.index)
>>> inconsistent value (re-run the example from read_csv and we'll get
... a different result).
  

Я пробовал разные другие вещи, например, используя index.data или index.to_native_types() или np.array(index.tolist()) вместо index.values , но я все равно получаю противоречивые результаты, поскольку я полагаю, что базовые данные могут отличаться.

Одна вещь, которая, кажется, работает до сих пор hashlib.sha1(np.array(df.index.format())).hexdigest() . Но это медленно, например, 2 минуты 34 секунды для (5000000,12) фрейма данных, тогда как само содержимое отпечатывается за 900 мс.

Есть предложения?

Ответ №1:

Иногда решение находится прямо у нас под носом…

 from sklearn.externals import joblib

%%time
joblib.hash(df, hash_name='sha1')
>>> consistent value that depends on values and axes
Wall time: 1.66 s  (for the (5000000,12) DataFrame mentioned above)