Проблема PyTables - разные результаты при переборе по подмножеству таблицы - PullRequest
3 голосов
/ 18 декабря 2009

Я новичок в 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]

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

1 Ответ

7 голосов
/ 19 декабря 2009

Это очень распространенная путаница при переборе объекта 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]

или

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

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

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

...