Добавление к HDFStore завершается сбоем, поскольку не может соответствовать существующей структуре таблицы.

Окончательное решение состояло в том, чтобы использовать параметр «конвертеры» read_csv и проверять каждое значение перед добавлением его в DataFrame. В конце концов, в более чем 80 ГБ необработанных данных было только 2 неверных значения.

Параметр выглядит следующим образом:

converters={'XXXXX': self.parse_xxxxx}

И небольшой статический вспомогательный метод, подобный этому:

@staticmethod
def parse_xxxxx(input):
    if not isinstance(input, float):
        try:
            return float(input)
        except ValueError:
            print "Broken Value: ", input
            return float(0.0)
    else:
         return input

При попытке прочитать ок. Более 40 ГБ CSV-данных в файл HDF. Я столкнулся с запутанной проблемой. После чтения около 1 ГБ весь процесс завершается со следующей ошибкой

File "/usr/lib/python2.7/dist-packages/pandas/io/pytables.py", line 658, in append
    self._write_to_group(key, value, table=True, append=True, **kwargs)
  File "/usr/lib/python2.7/dist-packages/pandas/io/pytables.py", line 923, in write_to_group
    s.write(obj = value, append=append, complib=complib, **kwargs)
  File "/usr/lib/python2.7/dist-packages/pandas/io/pytables.py", line 2985, in write **kwargs)
  File "/usr/lib/python2.7/dist-packages/pandas/io/pytables.py", line 2675, in create_axes
    raise ValueError("cannot match existing table structure for [%s] on appending data" % items)
ValueError: cannot match existing table structure for [Date] on appending data

Вызов read_csv, который я использую, выглядит следующим образом:

pd.io.parsers.read_csv(filename, sep=";|\t", compression='bz2', index_col=False, header=None, names=['XX', 'XXXX', 'Date', 'XXXXX'], parse_dates=[2], date_parser=self.parse_date, low_memory=False, iterator=True, chunksize=self.input_chunksize, dtype={'Date': np.int64})

Почему столбец «Дата» нового фрагмента не соответствует существующему столбцу, если я явно установил для dtypte значение int64?

Спасибо за вашу помощь!

Вот функция для разбора даты:

@staticmethod
def parse_date(input_date):
       import datetime as dt
       import re

       if not re.match('\d{12}', input_date):
           input_date = '200101010101'

        timestamp = dt.datetime.strptime(input_date, '%Y%m%d%H%M')
        return timestamp

Следуя некоторым советам Джеффа, я могу предоставить более подробную информацию о своей проблеме. Вот весь код, который я использую для загрузки файла в кодировке bz2:

iterator_data = pd.io.parsers.read_csv(filename, sep=";|\t", compression='bz2', index_col=False, header=None,
                                               names=['XX', 'XXXX', 'Date', 'XXXXX'], parse_dates=[2],
                                               date_parser=self.parse_date, iterator=True,
                                               chunksize=self.input_chunksize, dtype={'Date': np.int64})
for chunk in iterator_data:
    self.data_store.append('huge', chunk, data_columns=True)
    self.data_store.flush()

CSV-файл следует следующему шаблону: {STRING};{STRING};{STRING}\t{INT}.

Вывод ptdump -av, вызванный для выходного файла, следующий:

ptdump -av datastore.h5
/ (RootGroup) ''
  /._v_attrs (AttributeSet), 4 attributes:
   [CLASS := 'GROUP',
    PYTABLES_FORMAT_VERSION := '2.0',
    TITLE := '',
    VERSION := '1.0']
/huge (Group) ''
  /huge._v_attrs (AttributeSet), 14 attributes:
   [CLASS := 'GROUP',
    TITLE := '',
    VERSION := '1.0',
    data_columns := ['XX', 'XXXX', 'Date', 'XXXXX'],
    encoding := None,
    index_cols := [(0, 'index')],
    info := {'index': {}},
    levels := 1,
    nan_rep := 'nan',
    non_index_axes := [(1, ['XX', 'XXXX', 'Date', 'XXXXX'])],
    pandas_type := 'frame_table',
    pandas_version := '0.10.1',
    table_type := 'appendable_frame',
    values_cols := ['XX', 'XXXX', 'Date', 'XXXXX']]
/huge/table (Table(167135401,), shuffle, blosc(9)) ''
  description := {
  "index": Int64Col(shape=(), dflt=0, pos=0),
  "XX": StringCol(itemsize=16, shape=(), dflt='', pos=1),
  "XXXX": StringCol(itemsize=16, shape=(), dflt='', pos=2),
  "Date": Int64Col(shape=(), dflt=0, pos=3),
  "XXXXX": Int64Col(shape=(), dflt=0, pos=4)}
  byteorder := 'little'
  chunkshape := (2340,)
  autoIndex := True
  colindexes := {
    "Date": Index(6, medium, shuffle, zlib(1)).is_CSI=False,
    "index": Index(6, medium, shuffle, zlib(1)).is_CSI=False,
    "XXXX": Index(6, medium, shuffle, zlib(1)).is_CSI=False,
    "XXXXX": Index(6, medium, shuffle, zlib(1)).is_CSI=False,
    "XX": Index(6, medium, shuffle, zlib(1)).is_CSI=False}
  /huge/table._v_attrs (AttributeSet), 23 attributes:
   [XXXXX_dtype := 'int64',
    XXXXX_kind := ['XXXXX'],
    XX_dtype := 'string128',
    XX_kind := ['XX'],
    CLASS := 'TABLE',
    Date_dtype := 'datetime64',
    Date_kind := ['Date'],
    FIELD_0_FILL := 0,
    FIELD_0_NAME := 'index',
    FIELD_1_FILL := '',
    FIELD_1_NAME := 'XX',
    FIELD_2_FILL := '',
    FIELD_2_NAME := 'XXXX',
    FIELD_3_FILL := 0,
    FIELD_3_NAME := 'Date',
    FIELD_4_FILL := 0,
    FIELD_4_NAME := 'XXXXX',
    NROWS := 167135401,
    TITLE := '',
    XXXX_dtype := 'string128',
    XXXX_kind := ['XXXX'],
    VERSION := '2.6',
    index_kind := 'integer']

После большого количества дополнительной отладки я получил следующую ошибку:

ValueError: invalid combinate of [values_axes] on appending data [name->XXXX,cname->XXXX,dtype->int64,shape->(1, 10)] vs current table [name->XXXX,cname->XXXX,dtype->string128,shape->None]

Затем я попытался исправить это, добавив изменение вызова read_csv, чтобы задать правильный тип для столбца XXXX, но только что получил ту же ошибку:

dtype={'XXXX': 's64', 'Date': dt.datetime})

read_csv игнорирует настройки dtype или что я здесь упускаю?

При чтении данных с размером фрагмента 10 последние 2 вызова chunk.info() дают следующий результат:

Int64Index: 10 entries, 0 to 9
Data columns (total 4 columns):
XX         10  non-null values
XXXX       10  non-null values
Date       10  non-null values
XXXXX      10  non-null values
dtypes: datetime64[ns](1), int64(1), object(2)<class 'pandas.core.frame.DataFrame'>
Int64Index: 10 entries, 0 to 9
Data columns (total 4 columns):
XX         10  non-null values
XXXX       10  non-null values
Date       10  non-null values
XXXXX      10  non-null values
dtypes: datetime64[ns](1), int64(2), object(1)

Я использую панды версии 0.12.0.


person FrozenSUSHI    schedule 20.05.2014    source источник
comment
хорошо покажите существующую таблицу и образец того, что вы пытаетесь сохранить (покажите df.info()), а также версию pandas   -  person Jeff    schedule 21.05.2014
comment
stackoverflow.com/questions/15488809/ может помочь вам устранить неполадки   -  person Jeff    schedule 21.05.2014
comment
также, пожалуйста, покажите неточный код для чтения и записи   -  person Jeff    schedule 21.05.2014
comment
также покажите ptdump -av ‹out.hdf›   -  person Jeff    schedule 21.05.2014
comment
Я получил много дополнительной информации, но read_csv, похоже, игнорирует установленные мной dtypes.   -  person FrozenSUSHI    schedule 23.05.2014
comment
какая версия панды? показать chunk.dtypes, когда он поднимается   -  person Jeff    schedule 23.05.2014
comment
Я добавил информацию о версии, а также dtypes для конфликтующего добавления.   -  person FrozenSUSHI    schedule 23.05.2014


Ответы (1)


хорошо, у вас есть пара вопросов:

  • при указании dtypes для передачи в read_csv они должны быть numpy dtypes; и строковые dtypes преобразуются в object dtype (поэтому s64 ничего не делает). также не datetime, это то, что используется parse_dates.

  • ваши dtypes в разных чанках РАЗНЫЕ, то есть в первом у вас 2 столбца int64 и 1 object, а во втором - 1 int64 и 2 object. Это твоя проблема. (Я думаю, что сообщение об ошибке может быть немного запутанным, что исправлено IIRC в более поздних версиях pandas).

Итак, вам нужно, чтобы ваши dtypes в КАЖДОМ фрагменте были одинаковыми. У вас могут быть смешанные данные в этом конкретном столбце. Один из способов сделать это — указать dtype = { column_that_is_bad : 'object' }. Другой способ — использовать convert_objects(convert_numeric=True) В ЭТОМ столбце, чтобы привести все нечисловые значения к nan (это также изменит dtype столбца на float64).

person Jeff    schedule 23.05.2014
comment
Даже после изменения dtype на: dtype={'XX': 'object', 'XXXX': 'object', 'Date': 'object', 'XXXXX': 'uint64'}) обновление до Pandas 0.13.1 I получить это: ValueError: неверная комбинация [values_axes] при добавлении данных [name-> XXXXX, cname-> XXXXX, dtype-> float64, shape-> (1, 10000000)] против текущей таблицы [name-> XXXXX, cname- ›XXXXX,dtype-›int64,shape-›Нет] - person FrozenSUSHI; 24.05.2014
comment
вам нужно согласовать dtypes, прежде чем вы запишете их в HDF, посмотрите на df.dtypes каждого фрагмента, прежде чем писать их. некоторые данные изменяют их (например, у вас могут быть отсутствующие значения в одном, но не в другом). Вам нужно привести к правильному формату. - person Jeff; 24.05.2014
comment
Смешанные dtypes тоже были моей проблемой. Это запутанное сообщение об ошибке все еще существует, начиная с pandas 0.20.3 для hdf. - person ClimbsRocks; 02.10.2017