Можно ли использовать словарь в качестве полного ввода в matplotlib.pyplot? - PullRequest
1 голос
/ 15 мая 2019

Я настраиваю некоторый код таким образом, чтобы перед построением графика пользователь мог в основном сохранить все переменные построения, которые он хочет использовать в словаре, и эти записи будут сохранены для последующего использования. Ключи словаря следуют синтаксису ключевых слов matplotlib.pyplot. Примером этого словаря будет что-то вроде этого:

plot_info = {'title':'A neato title!',
             'x':[1,2,3,4],
             'y':[5,6,7,8],
             'grid':'on'}

Как мне включить этот словарь в команду plot для выполнения ключей в качестве аргументов и параметров в качестве входных данных для этих аргументов?

До сих пор я пытался:

import matplotlib.pyplot as plt
plot_info = {'title':'A neato title!',
             'x':[1,2,3,4],
             'y':[5,6,7,8],
             'grid':'on'}
plt.plot(**plot_info)

Ожидая, что это поможет. Однако после выполнения кода фигура всплывает, но фигура пуста, и все пусто (работает без ошибок, но открывает пустую фигуру).

Я ожидаю, что на выходе отобразится график, заголовок которого, значения x и y соответствуют значениям словаря и чья сетка включена. Есть идеи, почему этот участок будет пустым?

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

Ответы [ 3 ]

1 голос
/ 15 мая 2019

Нет, вы не можете сделать это с plt.plot. Причина в том, что подпись для plt.plot гласит:

def plot(*args, scalex=True, scaley=True, data=None, **kwargs)

Первый параметр, args, который получает данные для построения графика, является параметром var-positional . См. Определение параметр из глоссария:

параметр

Именованная сущность в определении функции (или метода), которая задает аргумент (или, в некоторых случаях, аргументы), который может принимать функция. Существует пять видов параметров:

позиционное-или-ключевое слово : указывает аргумент, который можно передать либо позиционно , либо как аргумент ключевого слова . Это тип параметра по умолчанию, например, foo и bar в следующем:

def func(foo, bar=None): ...

только для позиции : указывает аргумент, который может быть предоставлен только позицией. В Python нет синтаксиса для определения только позиционных параметров. Однако некоторые встроенные функции имеют только позиционные параметры (например, abs()).

только для ключевых слов : указывает аргумент, который может быть предоставлен только по ключевому слову. Параметры только для ключевого слова могут быть определены путем включения одного параметра var-positional или только * в список параметров определения функции перед ними, например, kw_only1 и kw_only2 в следующее:

def func(arg, *, kw_only1, kw_only2): ...

var-positional : указывает, что может быть предоставлена ​​произвольная последовательность позиционных аргументов (в дополнение к любым позиционным аргументам, уже принятым другими параметрами). Такой параметр может быть определен путем добавления имени параметра к *, например args в следующем:

def func(*args, **kwargs): ...

var-keyword : указывает, что может быть предоставлено произвольно много аргументов ключевого слова (в дополнение к любым аргументам ключевого слова, уже принятым другими параметрами). Такой параметр может быть определен путем добавления имени параметра к **, например, kwargs в приведенном выше примере.

Параметры могут указывать как необязательные, так и обязательные аргументы, а также значения по умолчанию для некоторых необязательных аргументов.

См. Также запись в глоссарии аргумент , вопрос FAQ по разница между аргументами и параметрами , класс inspect.Parameter, функция определения раздел и PEP 362 .

Вы можете указывать аргументы только для позиционных или ключевых слов или только для ключевых слов параметров со словарем. Параметр var-positional args не является ни тем, ни другим, поэтому его нельзя заполнить.

Кстати, что касается приведенного выше определения для только для позиционных параметров, правильный синтаксис для них был принят в PEP 570 .

0 голосов
/ 16 мая 2019

Ответ Reedinationer - это уже хорошее начало, я бы предложил вместо этого создать класс, например:

import matplotlib.pyplot as plt

class CustomPlot(object):
    """docstring for CustomPlot"""
    def __init__(self, plot_dict):
        super(CustomPlot, self).__init__()
        self.plot_dict = plot_dict
        ## you should also include some kind of "validation" here
        ## which verifies the plot_dict key:value pairs 
        self.make_plot()
        plt.show()

    def make_plot(self):
        fig,ax=plt.subplots()
        for k,v in self.plot_dict.items():
            if isinstance(v,dict):
                print(k)
                if k=='plot':
                    eval('plt.plot({x},{y})'.format(**v))
            else:
                print(v)
                eval('plt.{0}("{1}")'.format(k,v) )

plot_info = {
    'title':'A neato title!',
    'plot':{    
        'x':[1,2,3,4],
        'y':[5,6,7,8],
    },
    'grid':'True'
}

p=CustomPlot(plot_info)

Примечание: Я используюeval() здесь, что не совсем чистый способ сделать это.Это потребует, чтобы вы правильно проверили словарь , прежде чем передать его eval(), и действительно, действительно, протестировали это.Например, в вашем примере вы предложили вызвать plt.plot() с аргументом title, который не соответствует синтаксису ключевого слова matplotlib.pyplot, как вы изначально предполагали.Это ошибка, которая может также произойти с вашими потенциальными пользователями, и вам необходимо учесть это (т.е. сделать свою собственную обработку ошибок).Возможно, было бы лучше создать, например, словарь разрешенных вызовов функций и ожидаемых типов, а затем использовать его для проверки.

Кроме того, такой класс будет только началом , вам следует рассмотреть следующееопределение дополнительных вспомогательных функций, таких как def loads_data(), def store_dict() и других, чтобы все было продуманно.

0 голосов
/ 15 мая 2019

Я не думаю, что вы спрашиваете, возможно. plt.plot() не имеет grid или title аргументов . Вместо этого эти аргументы будут переданы plt самой ! Для этого вам понадобится несколько строк кода (поскольку это разные методы объекта plt), например:

import matplotlib.pyplot as plt

plt.plot([1, 2, 3, 4],
         [5, 6, 7, 8])

plt.grid(True)
plt.title('A neato title!')

plt.show()

Чтобы сделать действительный скрипт. Я не уверен, что ваше предполагаемое решение легче / красивее, чем встроенный функционал, так как вам все равно придется указывать аргументы. Если вы пытаетесь реализовать значения по умолчанию, возможно, функция сработает (вы могли бы расширить этот пример, чтобы тоже распаковать словарь):

def plot_my_data(x=(1, 2, 3, 4),
                 y=(5, 6, 7, 8),
                 grid_flag=True,
                 title='A neato title!'):
    plt.plot(x, y)
    plt.grid(grid_flag)
    plt.title(title)

Где сейчас простой

plot_my_data()
plt.show()

Дает ожидаемый

output graph

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...