сохранить масштаб масштаба и местоположение курсора после анимации matplotlib [дубликат]

Я знаю, что уже есть много ответов и столько комментариев, что они не сработают. Единственный консенсус в том, что он настолько сложный, что никто не сделал для него стандарта . Однако большинство принятых ответов в SO раскрывают «простые трюки», которые широко используются. Итак, для всех нас, как и я, которые не являются экспертами, но хотят писать более безопасный код, хватая немного больше на сложность javascript, я попытаюсь пролить некоторый свет.

Прежде чем загрязнять руки, пусть я уточняю 2 пункта:

  • [ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ] Я предлагаю функцию ниже, которая решает, как мы глубокий цикл в объекты javascript для копирования и иллюстрирует что, как правило, слишком кратко комментируется. Это не готово к производству. Ради ясности, я purposedly оставить в стороне других соображения, такие как круговые объекты (дорожки с помощью набора или unconflicting свойства символа) , копирование опорного значения или глубокого клона , неизменное объект назначения (глубокий клон снова?), в каждом конкретном случае исследование каждого типа объектов , get / set свойства через accessors ... Кроме того, я не тестировал производительность - хотя это важно, потому что здесь дело не в этом.
  • Я использую copy или присваивать термины вместо merge . Потому что, по моему мнению, слияние является консервативным и должно терпеть неудачу при конфликтах. Здесь, когда мы конфликтуем, мы хотим, чтобы источник перезаписывал адресат. Как Object.assign делает.

Ответы с for..in или Object.keys вводят в заблуждение

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

Когда я впервые прочитал ответ Салакара , я искренне думал, что смогу сделать лучше и проще ( вы можете сравнить его с Object.assign на x={a:1}, y={a:{b:1}}). Затем я прочитал ответ the8472 , и я подумал ... нет так легко уйти, что улучшение уже предоставленных ответов не заставит нас далеко.

Давайте дадим глубокую копию и рекурсивную в одно мгновение. Просто подумайте, как (ошибочно) люди анализируют свойства для копирования очень простого объекта.

const y = Object.create(
    { proto : 1 },
    { a: { enumerable: true, value: 1},
      [Symbol('b')] : { enumerable: true, value: 1} } )

Object.assign({},y)
> { 'a': 1, Symbol(b): 1 } // All (enumerable) properties are copied

((x,y) => Object.keys(y).reduce((acc,k) => Object.assign(acc, { [k]: y[k] }), x))({},y)
> { 'a': 1 } // Missing a property!

((x,y) => {for (let k in y) x[k]=y[k];return x})({},y)
> { 'a': 1, 'proto': 1 } // Missing a property! Prototype's property is copied too!

Object.keys будет опускать собственные неперечислимые свойства, собственные свойства с символьными ключами и все свойства прототипа. Это может быть хорошо, если у ваших объектов нет таких. Но имейте в виду, что Object.assign обрабатывает собственные перечислимые свойства с символьными ключами. Таким образом, ваша пользовательская копия потеряла свой цвет.

for..in предоставит свойства источника, его прототипа и полной цепи прототипов, если вы этого не захотите (или зная об этом).

Если вы пишете функцию общего назначения, и вы не используете Object.getOwnPropertyDescriptors, Object.getOwnPropertyNames, Object.getOwnPropertySymbols, вы можете использовать слишком много свойств, смешивая свойства прототипа и собственные свойства. ] или Object.getPrototypeOf, вы, скорее всего, ошибаетесь.

Что следует учитывать перед написанием вашей функции

Сначала убедитесь, что вы понимаете, что такое объект Javascript. В Javascript объект создается из его собственных свойств и (родительского) объекта прототипа. Объект прототипа, в свою очередь, состоит из его собственных свойств и прототипа. И т. Д., Определяя цепочку прототипов.

Свойство представляет собой пару ключей (string или symbol) и дескрипторов (value или get / set и атрибутов например enumerable).

Наконец, существует множество типов объектов . Вы можете захотеть иначе обрабатывать объект Object с объекта Date или объекта Function.

Итак, написав свою глубокую копию, вы должны ответить хотя бы на эти вопросы:

  1. Что я считаю глубоким (правильным для рекурсивного поиска) или плоским?
  2. Какие свойства я хочу скопировать? (перечисляемые / неперечислимые, строковые или с символьными ключами, собственные свойства / собственные свойства прототипа, значения / дескрипторы ...)

В моем примере я считаю, что только object Object s являются deep , потому что другие объекты, созданные другими конструкторами, могут быть неадекватными для углубленного просмотра. this []

function toType(a) {
    // Get fine type (object, array, function, null, error, date ...)
    return ({}).toString.call(a).match(/([a-z]+)(:?\])/i)[1];
}

function isDeepObject(obj) {
    return "Object" === toType(obj);
}

И я сделал объект options, чтобы выбрать, что копировать (для демонстрационной цели).

const options = {nonEnum:true, symbols:true, descriptors: true, proto:true};

Предлагаемая функция

Вы можете протестировать ее в этом plunker .

function deepAssign(options) {
    return function deepAssignWithOptions (target, ...sources) {
        sources.forEach( (source) => {

            if (!isDeepObject(source) || !isDeepObject(target))
                return;

            // Copy source's own properties into target's own properties
            function copyProperty(property) {
                const descriptor = Object.getOwnPropertyDescriptor(source, property);
                //default: omit non-enumerable properties
                if (descriptor.enumerable || options.nonEnum) {
                    // Copy in-depth first
                    if (isDeepObject(source[property]) && isDeepObject(target[property]))
                        descriptor.value = deepAssign(options)(target[property], source[property]);
                    //default: omit descriptors
                    if (options.descriptors)
                        Object.defineProperty(target, property, descriptor); // shallow copy descriptor
                    else
                        target[property] = descriptor.value; // shallow copy value only
                }
            }

            // Copy string-keyed properties
            Object.getOwnPropertyNames(source).forEach(copyProperty);

            //default: omit symbol-keyed properties
            if (options.symbols)
                Object.getOwnPropertySymbols(source).forEach(copyProperty);

            //default: omit prototype's own properties
            if (options.proto)
                // Copy souce prototype's own properties into target prototype's own properties
                deepAssign(Object.assign({},options,{proto:false})) (// Prevent deeper copy of the prototype chain
                    Object.getPrototypeOf(target),
                    Object.getPrototypeOf(source)
                );

        });
        return target;
    }
}

Это можно использовать следующим образом:

const x = { a: { a: 1 } },
      y = { a: { b: 1 } };
deepAssign(options)(x,y); // { a: { a: 1, b: 1 } }

-1
задан Pat 7 October 2016 в 12:03
поделиться

1 ответ

Да.

x = np.arange(10)
y = np.random.rand(10)

line, = plt.plot(x,y)
line.set_data(x,np.random.rand(10))
plt.draw()

Однако ваш график становится медленнее, потому что вы расширяете свой кадр данных, и каждая операция добавления, вероятно, копирует этот кадр в память в новое место. По мере увеличения размера фрейма данных эта операция копирования занимает больше времени. Я бы зациклил на индекс и график, что (for ii in range(len(data)): line.set_data(x[:ii], y[:ii]))

EDIT:

import numpy as np
import matplotlib.pyplot as plt; plt.ion()
import pandas as pd

n = 100
x = np.arange(n)
y = np.random.rand(n)
# I don't get the obsession with pandas...
df = pd.DataFrame(dict(time=x, value=y))

# initialise plot and line
line, = plt.plot(df['time'], df['value'])

# simulate line drawing
for ii in range(len(df)):
    line.set_data(df['time'][:ii], df['value'][:ii]) # couldn't be bothered to look up the proper way to index in pd
    plt.draw()
    plt.pause(0.001)
2
ответ дан Paul Brodersen 20 August 2018 в 07:39
поделиться
  • 1
    Могу ли я попросить вас предоставить пример на основе кода, который я опубликовал, пожалуйста. Большое спасибо, Pat. – Pat 7 October 2016 в 12:55
  • 2
    Спасибо, за редактирование. Ваш пример с [: ii] работает только в том случае, если вы заранее знали длину данных (n = 100), правильно? Используя цикл while и создавая новые добавленные данные в цикле while (как в моем примере), я должен сделать это другим способом. – Pat 7 October 2016 в 13:57
  • 3
    – Paul Brodersen 7 October 2016 в 14:11
  • 4
    Хммм. Я понимаю вашу мысль. Но то, что сейчас происходит, заключается в том, что у меня есть фид данных из финансовой информационной системы. Эти новые точки данных, которые приведены в этих примерах, добавленные данные сохраняются и вытаскиваются впоследствии из хранилища HDF. Моя цель состояла бы в том, чтобы иметь округлое окно качения последних n элементов из этого HDFstore. Таким образом, по моему мнению, нет причин, почему открытие цикла while и построение графика данных будет плохим выбором, поскольку программа теоретически может работать вечно. – Pat 7 October 2016 в 14:25
  • 5
    Ну, в настоящий момент это не будет продолжаться вечно, потому что скоро вы будете отставать от минут, если не за часами позади тикера (если вы действительно обновляете каждую микросекунду, как показывает ваш код). Просто инициализируйте массив достаточно большим в течение 1 часа или дня, а затем инициализируйте и добавьте новый массив того же размера, когда он будет заполнен. Кроме того, я действительно очень надеюсь, что вы не добавляете то же самое к своим файлам hdf5, потому что там у вас будет такая же проблема ... Примите ответ, он сделает то, что вы изначально попросили, и многое другое. – Paul Brodersen 7 October 2016 в 14:53
Другие вопросы по тегам:

Похожие вопросы: