2013-07-15 2 views
5

В Pandas есть ли способ эффективно вытащить все индексы MultiIndex, представленные в HDFStore в табличном формате?Pandas HDFStore MultiIndex DataFrames: как эффективно получить все индексы

Я могу select() эффективно использовать where=, но я хочу, чтобы все индексы и ни один из столбцов. Я также могу использовать select(), используя iterator=True, чтобы сохранить RAM, но это все равно означает чтение почти всей таблицы с диска, поэтому она все еще медленная.

Я охотился в store.root..table. * Материал, надеясь, что я получу список значений индекса. Я на правильном пути?

План B должен содержать более короткий MultiFinddeframe, который содержит только пустые DataFrames, добавляемые каждый раз, когда я добавляю основной. Я могу получить это и получить индекс намного дешевле, чем основной. Однако неэлегантно.

ответ

5

Создать мультииндекс ф.р.

In [35]: df = DataFrame(randn(100000,3),columns=list('ABC')) 

In [36]: df['one'] = 'foo' 

In [37]: df['two'] = 'bar' 

In [38]: df.ix[50000:,'two'] = 'bah' 

In [40]: mi = df.set_index(['one','two']) 

In [41]: mi 
Out[41]: 
<class 'pandas.core.frame.DataFrame'> 
MultiIndex: 100000 entries, (foo, bar) to (foo, bah) 
Data columns (total 3 columns): 
A 100000 non-null values 
B 100000 non-null values 
C 100000 non-null values 
dtypes: float64(3) 

магазин это в виде таблицы

In [42]: store = pd.HDFStore('test.h5',mode='w') 

In [43]: store.append('df',mi) 

get_storer вернет сохраненный объект (но не извлекать данные)

In [44]: store.get_storer('df').levels 
Out[44]: ['one', 'two'] 

In [2]: store 
Out[2]: 
<class 'pandas.io.pytables.HDFStore'> 
File path: test.h5 
/df   frame_table (typ->appendable_multi,nrows->100000,ncols->5,indexers->[index],dc->[two,one]) 

уровни индексов создаются как data_columns, что означает, что вы можете использовать их в выборе Это как выбрать только индекс

In [48]: store.select('df',columns=['one']) 
Out[48]: 
<class 'pandas.core.frame.DataFrame'> 
MultiIndex: 100000 entries, (foo, bar) to (foo, bah) 
Empty DataFrame 

Чтобы выбрать один столбец и возвращает его в качестве пц-кадра

In [49]: store.select('df',columns=['A']) 
Out[49]: 
<class 'pandas.core.frame.DataFrame'> 
MultiIndex: 100000 entries, (foo, bar) to (foo, bah) 
Data columns (total 1 columns): 
A 100000 non-null values 
dtypes: float64(1) 

Чтобы выбрать один столбец в виде ряда (который также может быть индекс, поскольку они хранятся в виде столбцов). Это будет довольно быстро.

In [2]: store.select_column('df','one') 
Out[2]:  
0     foo 
1     foo 
2     foo 
3     foo 
4     foo 
5     foo 
6     foo 
7     foo 
8     foo 
9     foo 
10    foo 
11    foo 
12    foo 
13    foo 
14    foo 
... 
99985    foo 
99986    foo 
99987    foo 
99988    foo 
99989    foo 
99990    foo 
99991    foo 
99992    foo 
99993    foo 
99994    foo 
99995    foo 
99996    foo 
99997    foo 
99998    foo 
99999    foo 
Length: 100000, dtype: object 

Если вы действительно хотите быстрый выбор только индекс

In [4]: %timeit store.select_column('df','one') 
100 loops, best of 3: 8.71 ms per loop 

In [5]: %timeit store.select('df',columns=['one']) 
10 loops, best of 3: 43 ms per loop 

Или, чтобы получить полный индекс

In [6]: def f(): 
    ...:  level_1 = store.select_column('df','one') 
    ...:  level_2 = store.select_column('df','two') 
    ...:  return MultiIndex.from_arrays([ level_1, level_2 ]) 
    ...: 

In [17]: %timeit f() 
10 loops, best of 3: 28.1 ms per loop 

Если вы хотите, чтобы значения для каждого уровня, довольно быстрый способ его проведения

In [2]: store.select_column('df','one').unique() 
Out[2]: array(['foo'], dtype=object) 

In [3]: store.select_column('df','two').unique() 
Out[3]: array(['bar', 'bah'], dtype=object) 
+0

Фантастический ответ, спасибо Джефф. Я полагаю, что прямой ответ заключается в том, что поиск в store.root. * Table бесполезен. При дальнейшем рассмотрении, вдохновленном вашим ответом, имеет смысл, что нет ярлыка - вы должны разрешить выбору рассматривать все данные. Попытка получить некоторые метаданные, чтобы указать, какие значения индекса просто будут занимать одно и то же пространство. В качестве объяснения не все возможные комбинации моего мультииндекса заполнены, поэтому просто получить уровни мультииндекса недостаточно. Спасибо. – Tony

+0

, вы можете найти '' select_column (...). Unique() '' полезно также, что фактически даст вам значения определенного уровня, не уверен, что это вам полезно – Jeff

+0

Я добавил метод I просто предложил – Jeff

1

Те, кто работает с еще большими таблицами, могут найти решение, предложенное Джеффом, в итоге с ошибкой памяти. Это гораздо более изящное решение, но я не мог использовать в своем случае (для таблицы строк 2e9, индекс datetime, на рабочем столе 16 ГБ оперативной памяти). я в конечном итоге со следующим (к сожалению, не элегантным) решением, где h5store является HDFStore объекта, мульти-индексированных DataFrame, сохраняются в виде таблицы, с timestamp индексом (Float64), который является CSI один:

%%time 
#ts = h5store.select_column(h5store.keys()[0], column='timestamp').unique() 

chunkshape = int(1e7) # can vary due to machine and hdf5 

## get a list of chunks unique timestamps 
ts = [indx.index.get_level_values('timestamp').unique() 
      for indx in h5full.select(h5full.keys()[0], columns=['timestamp'], 
            stop=None, # change for a smaller selection 
            chunksize=chunkshape) 
     ] 
## drop duplicates at the the end-points 
for i in range(len(ts)-1): 
    if ts[i][-1]==ts[i+1][0]: 
     ts[i] = ts[i][:-1] 
## merge to single ndarray 
ts = np.concatenate(ts) 

Время для этого прогона (более 2е9 строк):

CPU times: user 14min 16s, sys: 2min 34s, total: 16min 50s 
Wall time: 14min 45s 
Смежные вопросы