Проблема PyTables - разные результаты при переборе подмножества таблицы

Я новичок в PyTables и собираюсь использовать его для обработки данных, сгенерированных в результате моделирования на основе агентов и сохраненных в HDF5. Я работаю с тестовым файлом размером 39 МБ и наблюдаю некоторую странность. Вот раскладка стола:

    /example/agt_coords (Table(2000000,)) ''
  description := {
  "agent": Int32Col(shape=(), dflt=0, pos=0),
  "x": Float64Col(shape=(), dflt=0.0, pos=1),
  "y": Float64Col(shape=(), dflt=0.0, pos=2)}
  byteorder := 'little'
  chunkshape := (20000,)

Вот как я получаю к нему доступ в Python:

from tables import *
>>> h5file = openFile("alternate_hose_test.h5", "a")

h5file.root.example.agt_coords
/example/agt_coords (Table(2000000,)) ''
  description := {
  "agent": Int32Col(shape=(), dflt=0, pos=0),
  "x": Float64Col(shape=(), dflt=0.0, pos=1),
  "y": Float64Col(shape=(), dflt=0.0, pos=2)}
  byteorder := 'little'
  chunkshape := (20000,)
>>> coords = h5file.root.example.agt_coords

Теперь вот где вещи становятся странными.

[x for x in coords[1:100] if x['agent'] == 1]
[(1, 25.0, 78.0), (1, 25.0, 78.0)]
>>> [x for x in coords if x['agent'] == 1]
[(1000000, 25.0, 78.0), (1000000, 25.0, 78.0)]
>>> [x for x in coords.iterrows() if x['agent'] == 1]
[(1000000, 25.0, 78.0), (1000000, 25.0, 78.0)]
>>> [x['agent'] for x in coords[1:100] if x['agent'] == 1]
[1, 1]
>>> [x['agent'] for x in coords if x['agent'] == 1]
[1, 1]

Я не понимаю, почему значения искажаются, когда я перебираю всю таблицу, но не когда беру небольшое подмножество всего набора строк. Я уверен, что это ошибка в том, как я использую библиотеку, поэтому любая помощь в этом вопросе будет очень признательна.


person I82Much    schedule 18.12.2009    source источник


Ответы (1)


Это очень распространенная путаница при переборе Table объекта,

Когда вы перебираете Table, тип элемента, который вы получаете, — это не данные в элементе, а метод доступа к таблице в текущей строке. Так с

[x for x in coords if x['agent'] == 1]

вы создаете список методов доступа к строкам, которые все указывают на «текущую» строку таблицы, последнюю строку. Но когда вы делаете

[x["agent"] for x in coords if x['agent'] == 1]

вы используете метод доступа при создании списка.

Решение для получения всех необходимых данных при создании списка с использованием метода доступа на каждой итерации. Есть два варианта

[x[:] for x in coords if x['agent'] == 1]

or

[x.fetch_all_fields() for x in coords if x['agent'] == 1]

Первый строит список кортежей. Последний возвращает пустой объект NumPy. IIRC, второй быстрее, но первый может иметь больше смысла для ваших целей.

Вот хорошее объяснение от разработчика PyTables . В будущих выпусках печать объекта доступа к строке может быть не просто показать данные, но указать, что это объект доступа к строке.

person AFoglia    schedule 19.12.2009
comment
Спасибо за очень подробное объяснение неожиданного поведения. Я очень хочу, чтобы руководство (например, pytables.org/moin/HintsForSQLUsers , pytables.org/docs/manual/ch03.html (см. 3.1.6) отметил что ты объяснил - person I82Much; 21.12.2009