Анимация гистограммы с помощью Matplotlib (Python) - PullRequest
1 голос
/ 07 апреля 2020

Я недавно написал это, чтобы почистить журнал и показать график наиболее часто используемых в нем слов matplotlib.pyplot.bar

import re
from datetime import datetime
from collections import Counter

import matplotlib.pyplot as plt
from matplotlib import animation

def read_log(path, index, separator=chr(9)):
    data = []
    my_file = open(path,"r+")
    rows = my_file.readlines()
    for row in rows:
        line = re.sub(r'\r\n|\r|\n','',row, flags=re.M)
        if line != '':
            data.append(line.split(separator)[index])
    my_file.close()
    return Counter(data)

def set_plot(counter_data):
    plt.title('This is a title')
    plt.bar(range(len(counter_data)), list(counter_data.values()), align='center')
    plt.xticks(range(len(counter_data)), list(counter_data.keys()))
    plt.tight_layout()
    plt.show()

counter_data = read_log(r'logfile.txt',2)
print(counter_data)
set_plot(counter_data)

Я хотел бы оживить этот сюжет, однако не могу gr asp animation.FuncAnimation()

Вы можете мне помочь?

Я добавил эти строки:

fig = plt.Figure()
animation.FuncAnimation(fig, set_plot(counter_data), frames=20)

и удалил plt.show()

Так что я мог бы дать FuncAnimation пустую фигуру (рис.) И функцию. Но это не работает. РЕДАКТИРОВАТЬ: И это также не печатает ошибку.

Ответы [ 2 ]

0 голосов
/ 07 апреля 2020

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

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

У вас должна быть функция (animate в моей версии, set_plot в ваш), который обновляет сюжет для каждого шага вашей анимации. (в вашем случае вы просто помещаете одни и те же данные каждый раз)

Эта функция должна принимать хотя бы один параметр (val), который используется my FuncAnimation, который передает значения, полученные от итератора, переданные его frames параметр.

Окончательный код выглядит следующим образом

import re
from datetime import datetime
from collections import Counter
import matplotlib.pyplot as plt
from matplotlib import animation
# uncomment if using in jupyter notebook
# %matplotlib nbagg 

def read_log(path, index, separator=chr(9)):
    data = []
    my_file = open(path,"r+")
    rows = my_file.readlines()
    for row in rows:
        line = re.sub(r'\r\n|\r|\n','',row, flags=re.M)
        if line != '':
            data.append(line.split(separator)[index])
    my_file.close()
    return Counter(data)

fig = plt.figure()
ax = fig.add_subplot()
counter_data = read_log(r'tmp.csv',2)
plt.title('This is a title')
bar = ax.bar(range(len(counter_data)), list(counter_data.values()), align='center')
plt.xticks(range(len(counter_data)), list(counter_data.keys()))
plt.tight_layout()
plt.ylim((0, 30))


def animate(val, counter_data):
    data = list(counter_data.values())
    for i in range(len(data)):
        bar[i].set_height(data[i]+val)

animation.FuncAnimation(fig, func=animate, frames=20, fargs=[counter_data], save_count=10)

, и мы получаем следующую анимацию:

animation


Редактировать :

При ошибках вы можете попытаться сохранить анимацию в формате GIF, и ошибки будут отображаться

anim = animation.FuncAnimation(fig, func=animate, frames=20, fargs=[counter_data], save_count=10)
anim.save('anim.gif', 'imagemagick')

0 голосов
/ 07 апреля 2020

Основная проблема заключается в том, что FuncAnimation ожидает вызова, который возвращает объекты художника. Вызываемый будет вызываться повторно с аргументом фрейма.

В вашем примере set_plot() вызывается один раз. Возвращаемое значение (None) передается в FuncAnimation. Вместо этого у вас должен быть метод, например update_plot(), который загружает данные из файла, обновляет гистограмму и возвращает гистограмму. Эта функция (сама функция) должна быть передана в FuncAnimation

 animation.FuncAnimation(fig, update_plot, frames=20)

без вызова ее! Обратите внимание на пропущенные скобки после update_plot. документация по анимации показывает примеры, как это можно сделать.

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