Временная метка Pandas в json и из json

#python #json #pandas #numpy

#python #json #pandas #numpy

Вопрос:

Объекты не могут быть сериализованы в json, поэтому их необходимо преобразовать или проанализировать с помощью пользовательского класса JSONEncoder.

фрейм данных pandas имеет ряд методов, таких from_records как чтение данных json. Однако, когда вы считываете эти данные json обратно, они возвращаются как int64 вместо метки времени.

Существует много способов скинуть кошку в pandas. Каков наилучший способ сохранить структуры данных при чтении и записи json?

Комментарии:

1. Pandas не является универсальным декодером json. Он может (корректно) обрабатывать только файлы json определенного формата и, как известно, плохо справляется с обработкой глубоко вложенных файлов json. ИМХО, ваш текущий вопрос неясен .

2. @SergeBallesta вопрос в том, что pandas по какой-то причине проделал хакерскую работу по преобразованию данных в json и из него. попробуйте записать из pandas df в json что-нибудь, что содержит pd. Отметьте объект Timestamp, а затем прочитайте его обратно в df. у вас будет два разных объекта

Ответ №1:

Как бы то ни было, я сохраняю фреймы данных pandas в базе данных Postgres, и я хочу сохранить индекс с временным интервалом. Я использую следующий код:

 class db_JsonEncodedDataFrameWithTimezone(db.TypeDecorator):
    """Enables JSON storage by encoding and decoding on the fly."""
    impl = db.Text

    def process_bind_param(self, value, dialect):
        if value is not None and isinstance(value, pd.DataFrame):
            timezone = value.index.tz.zone
            df_json = value.to_json(orient="index")
            data = {'timezone': timezone, 'df': df_json, 'index_name': value.index.name}
            value = json.dumps(data)
        return value

    def process_result_value(self, value, dialect):
        if value is not None:
            data = json.loads(value)
            df = pd.read_json(data['df'], orient="index")
            df.index = df.index.tz_localize('UTC')
            df.index = df.index.tz_convert(data['timezone'])
            df.index.name = data['index_name']
            value = df
        return value

    def compare_values(self, x, y):
        from pandas.util.testing import assert_frame_equal
        try:
            assert_frame_equal(x, y, check_names=True, check_like=True)
            return True
        except (AssertionError, ValueError, TypeError):
            return False
  

Комментарии:

1. похоже, что json не подходит для сериализации временных меток или других объектов. спасибо за альтернативу!

Ответ №2:

Если я правильно понял вашу проблему, вы ищете способ сериализации, сохраняющий типы данных фрейма данных.

Проблема в том, что форматы обмена внутри используют несколько типов: только строки для csv, строки и числа для json. Конечно, есть способы давать подсказки по форматированию во время чтения (формат даты для столбцов даты в csv), и, как правило, легко преобразовать обратно в правильный тип после извлечения, я думаю, что вы надеетесь более естественным способом. Как было предложено Attack68, вы могли бы использовать базу данных, но, например, база данных SQLite была бы отключена, поскольку у нее нет внутреннего типа даты.

ИМХО, простым способом было бы положиться на старый добрый pickle модуль. В конце концов, фрейм данных — это объект Python, который содержит другие объекты Python, поэтому pickle хорош в сериализации этого. Единственное, что следует помнить, это то, что во время десериализации pandas должны быть импортированы перед вызовом pickle.load .

Но я только что протестировал с (крошечным) фреймом данных, содержащим различные типы данных, и pickle был великолепен, поскольку правильно сохранял и восстанавливал их.