산점도를 애니메이션하는 방법은 무엇입니까?


83

애니메이션의 다른 단계에서 포인트의 색상과 크기가 변경되는 산점도의 애니메이션을 만들려고합니다. 데이터의 경우 x 값과 y 값이있는 두 개의 numpy ndarray가 있습니다.

data.shape = (ntime, npoint)
x.shape = (npoint)
y.shape = (npoint)

이제 유형의 산점도를 플로팅하고 싶습니다.

pylab.scatter(x,y,c=data[i,:])

인덱스 위에 애니메이션을 만듭니다 i. 어떻게해야합니까?


2
matplotlib 문서에는 Rain 시뮬레이션 예제가 있습니다 .
ImportanceOfBeingErnest

답변:


142

산점도가 있다고 가정하면 scat = ax.scatter(...)다음을 수행 할 수 있습니다.

  • 위치를 바꾸다

          scat.set_offsets(array)
    

여기서 arrayA는 N x 2x 및 y 좌표의 모양 배열.

  • 크기 변경

          scat.set_sizes(array)
    

여기서 array포인트 크기의 1 차원 배열이다.

  • 색을 바꾸다

          scat.set_array(array)
    

여기서 arraycolormapped 될 값들의 1 차원 어레이이다.

다음은 애니메이션 모듈을 사용하는 간단한 예 입니다.
필요한 것보다 약간 더 복잡하지만 더 멋진 일을 할 수있는 프레임 워크를 제공해야합니다.

(현재 버전과 호환되도록 2019 년 4 월에 편집 된 코드. 이전 코드는 개정 내역 참조 )

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

class AnimatedScatter(object):
    """An animated scatter plot using matplotlib.animations.FuncAnimation."""
    def __init__(self, numpoints=50):
        self.numpoints = numpoints
        self.stream = self.data_stream()

        # Setup the figure and axes...
        self.fig, self.ax = plt.subplots()
        # Then setup FuncAnimation.
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=5, 
                                          init_func=self.setup_plot, blit=True)

    def setup_plot(self):
        """Initial drawing of the scatter plot."""
        x, y, s, c = next(self.stream).T
        self.scat = self.ax.scatter(x, y, c=c, s=s, vmin=0, vmax=1,
                                    cmap="jet", edgecolor="k")
        self.ax.axis([-10, 10, -10, 10])
        # For FuncAnimation's sake, we need to return the artist we'll be using
        # Note that it expects a sequence of artists, thus the trailing comma.
        return self.scat,

    def data_stream(self):
        """Generate a random walk (brownian motion). Data is scaled to produce
        a soft "flickering" effect."""
        xy = (np.random.random((self.numpoints, 2))-0.5)*10
        s, c = np.random.random((self.numpoints, 2)).T
        while True:
            xy += 0.03 * (np.random.random((self.numpoints, 2)) - 0.5)
            s += 0.05 * (np.random.random(self.numpoints) - 0.5)
            c += 0.02 * (np.random.random(self.numpoints) - 0.5)
            yield np.c_[xy[:,0], xy[:,1], s, c]

    def update(self, i):
        """Update the scatter plot."""
        data = next(self.stream)

        # Set x and y data...
        self.scat.set_offsets(data[:, :2])
        # Set sizes...
        self.scat.set_sizes(300 * abs(data[:, 2])**1.5 + 100)
        # Set colors..
        self.scat.set_array(data[:, 3])

        # We need to return the updated artist for FuncAnimation to draw..
        # Note that it expects a sequence of artists, thus the trailing comma.
        return self.scat,


if __name__ == '__main__':
    a = AnimatedScatter()
    plt.show()

여기에 이미지 설명 입력

당신은 OSX에와 OSX 백엔드를 사용하는 경우, 당신은 변경해야합니다 blit=Trueblit=FalseFuncAnimation아래의 초기화. OSX 백엔드는 블리 팅을 완전히 지원하지 않습니다. 성능이 저하되지만 블리 팅이 비활성화 된 OSX에서 예제가 올바르게 실행되어야합니다.


색상 만 업데이트하는 간단한 예제는 다음을 참조하십시오.

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation

def main():
    numframes = 100
    numpoints = 10
    color_data = np.random.random((numframes, numpoints))
    x, y, c = np.random.random((3, numpoints))

    fig = plt.figure()
    scat = plt.scatter(x, y, c=c, s=100)

    ani = animation.FuncAnimation(fig, update_plot, frames=range(numframes),
                                  fargs=(color_data, scat))
    plt.show()

def update_plot(i, data, scat):
    scat.set_array(data[i])
    return scat,

main()

안녕하세요 Joe 첫 번째 예제를 시도했지만 두 번째 예제는 작동하지 않습니다. 아마도 첫 번째 옵션을 디버깅하려고 할 것입니다. 이것은 파이썬 지식을 향상시키는 데 도움이 될 것입니다. 감사합니다
Nicola Vianello

1
불행히도 첫 번째 예제는 OS X에서 matplotlib 1.3.1을 사용하여 나에게 표시되지 않습니다. 프레임에 포인트가 표시되지 않습니다. 두 번째 예가 작동합니다.
JoshAdel

9
그것이 .set_array()도트 컬러를 업데이트 할 것이라는 것을 어떻게 알았습니까 ?!
Lucas

1
첫 번째 예는 작동하지 않습니다. 라인 self.Scat.set_offsets(data[:2, :]) 을 변경해야합니다 . self.scat.set_offsets(data[:2, :].reshape(self.numpoints, 2))
AN O'Nyme

2
스 캐터 포인트의 마커를 변경하는 기능이 있습니까?
콘스탄티노스

13

저는 이것을 쉽게하기 위해 셀룰로이드 를 썼습니다 . 예를 들어 보여주는 것이 가장 쉽습니다.

import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from celluloid import Camera

numpoints = 10
points = np.random.random((2, numpoints))
colors = cm.rainbow(np.linspace(0, 1, numpoints))
camera = Camera(plt.figure())
for _ in range(100):
    points += 0.1 * (np.random.random((2, numpoints)) - .5)
    plt.scatter(*points, c=colors, s=100)
    camera.snap()
anim = camera.animate(blit=True)
anim.save('scatter.mp4')

여기에 이미지 설명 입력

ArtistAnimation후드 아래에서 사용 합니다. camera.snap애니메이션에서 프레임을 만드는 데 사용되는 Figure의 현재 상태를 캡처합니다.

편집 : 이것이 사용하는 메모리 양을 정량화하기 위해 memory_profiler를 통해 실행했습니다 .

Line #    Mem usage    Increment   Line Contents
================================================
    11     65.2 MiB     65.2 MiB   @profile
    12                             def main():
    13     65.2 MiB      0.0 MiB       numpoints = 10
    14     65.2 MiB      0.0 MiB       points = np.random.random((2, numpoints))
    15     65.2 MiB      0.1 MiB       colors = cm.rainbow(np.linspace(0, 1, numpoints))
    16     65.9 MiB      0.6 MiB       fig = plt.figure()
    17     65.9 MiB      0.0 MiB       camera = Camera(fig)
    18     67.8 MiB      0.0 MiB       for _ in range(100):
    19     67.8 MiB      0.0 MiB           points += 0.1 * (np.random.random((2, numpoints)) - .5)
    20     67.8 MiB      1.9 MiB           plt.scatter(*points, c=colors, s=100)
    21     67.8 MiB      0.0 MiB           camera.snap()
    22     70.1 MiB      2.3 MiB       anim = camera.animate(blit=True)
    23     72.1 MiB      1.9 MiB       anim.save('scatter.mp4')

요약하면 다음과 같습니다.

  • 100 개의 플롯을 만드는 데 1.9MiB가 사용되었습니다.
  • 애니메이션 제작에는 2.3MiB가 사용되었습니다.
  • 이 애니메이션 제작 방법은 총 4.2MiB의 메모리를 사용했습니다.

1
이것은 ArtistAnimation을 사용하기 때문에 메모리에 100 개의 산점도를 생성하는데 이는 다소 비효율적입니다. 성능이 중요하지 않은 경우에만 사용하십시오.
ImportanceOfBeingErnest

1
메모리 프로파일 링은 좋은 생각입니다. 당신은 똑같이 했습니까 FuncAnimation? 차이점은 무엇입니까?
ImportanceOfBeingErnest

1
애니메이션을 어떻게 표시합니까 (파일에 저장하는 것과 같이)?
argentum2f

5

여기에 문제가 있습니다. 나는 Qt와 Matlab 사용자에게 익숙했고 matplotlib의 애니메이션 시스템에 익숙하지 않습니다.

하지만 MATLAB 에서처럼 원하는 모든 종류의 애니메이션을 만들 수있는 방법을 찾았습니다. 정말 강력합니다. 모듈 참조를 확인할 필요가 없으며 원하는 것을 플로팅하는 것이 좋습니다. 그래서 도움이 되길 바랍니다.

기본 아이디어는 PyQt 내부에서 시간 이벤트를 사용하는 것입니다 (wxPython 및 TraitUi와 같은 Python의 다른 Gui 시스템이 이벤트 응답을 만드는 동일한 내부 메커니즘을 가지고 있다고 확신합니다.하지만 방법을 모르겠습니다). PyQt의 Timer 이벤트가 호출 될 때마다 전체 캔버스를 새로 고치고 전체 그림을 다시 그립니다. 속도와 성능이 느리게 영향을받을 수 있다는 것을 알고 있지만 그다지 많지는 않습니다.

여기에 대한 간단한 예가 있습니다.

import sys
from PyQt4 import QtGui

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas

import numpy as np


class Monitor(FigureCanvas):
    def __init__(self):
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)

        FigureCanvas.__init__(self, self.fig)
        self.x = np.linspace(0,5*np.pi,400)
        self.p = 0.0
        self.y = np.sin(self.x+self.p)


        self.line = self.ax.scatter(self.x,self.y)

        self.fig.canvas.draw()

        self.timer = self.startTimer(100)


    def timerEvent(self, evt):
        # update the height of the bars, one liner is easier
        self.p += 0.1
        self.y = np.sin(self.x+self.p)
        self.ax.cla()
        self.line = self.ax.scatter(self.x,self.y)

        self.fig.canvas.draw()



if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    w = Monitor()
    w.setWindowTitle("Convergence")
    w.show()
    sys.exit(app.exec_())

새로 고침 속도를 조정할 수 있습니다.

        self.timer = self.startTimer(100)

애니메이션 산점도를 사용하여 정렬 애니메이션을 만들고 싶은 분들과 똑같습니다. 그러나 소위 "set"함수를 찾을 수 없습니다. 그래서 캔바 전체를 새로 고쳤습니다.

도움이 되었기를 바랍니다 ..


정말 좋아요! 그러나 self.startTimer값 을 조정해도 새로 고침 빈도가 변경되지 않았습니다. 그에 대한 팁이 있습니까? (그래, 난 ... 그것은 오랜만 것을 알고)
H. Arponen에게

-1

이것을 시도하지 않는 이유

import numpy as np
import matplotlib.pyplot as plt

x=np.random.random()
y=np.random.random()

fig, ax = plt.subplots()
ax.scatter(x,y,color='teal')
ax.scatter(y,x,color='crimson')
ax.set_xlim([0,1])
ax.set_ylim([0,1])

for i in np.arange(50):
    x=np.random.random()
    y=np.random.random()
    bha=ax.scatter(x,y)
    plt.draw()
    plt.pause(0.5)
    bha.remove()

plt.show()

왜 이것이 반대표를 받았습니까? 작동하지 않습니까?
eric
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.