Mấu chốt ở đây là sử dụng một Collection
. Trong trường hợp của bạn, bạn muốn tạo một PatchCollection
.
Matplotlib tối ưu hóa việc vẽ nhiều nghệ sĩ tương tự thông qua việc sử dụng bộ sưu tập. Nó nhanh hơn nhiều so với việc vẽ từng cái một. Hơn nữa, cốt truyện sẽ không chứa hàng ngàn nghệ sĩ riêng lẻ, chỉ có một bộ sưu tập. Điều này tăng tốc độ nhiều hoạt động linh tinh khác cần phải hoạt động trên mỗi nghệ sĩ mỗi lần vẽ.
scatter
thực sự là nhiều hơn nhanh hơn phương pháp hiện tại của bạn vì sẽ thêm bộ sưu tập thay vì các nghệ sĩ riêng biệt. Tuy nhiên, nó cũng vẽ các điểm đánh dấu với kích thước không nằm trong tọa độ dữ liệu.
Để khắc phục điều đó, bạn có thể sử dụng cùng cách tiếp cận scatter
, nhưng tạo bộ sưu tập theo cách thủ công.
Như một ví dụ:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.collections
num = 5000
sizes = 0.2 * np.random.random(num)
xy = 50 * np.random.random((num, 2))
# Note that the patches won't be added to the axes, instead a collection will
patches = [plt.Circle(center, size) for center, size in zip(xy, sizes)]
fig, ax = plt.subplots()
coll = matplotlib.collections.PatchCollection(patches, facecolors='black')
ax.add_collection(coll)
ax.margins(0.01)
plt.show()
này làm khá suôn sẻ đối với tôi.Chỉ để chứng minh rằng các vòng tròn là ở tọa độ dữ liệu, lưu ý những gì sẽ xảy ra nếu chúng ta phóng to trên một hình chữ nhật hẹp (lưu ý: điều này giả định rằng các khía cạnh của cốt truyện được thiết lập để auto
):
Nếu bạn thực sự tập trung vào tốc độ, bạn có thể sử dụng EllipseCollection
như @tcaswell đề xuất.
An EllipseCollection
sẽ chỉ thực hiện một đường dẫn, nhưng sẽ mở rộng và dịch tại thời điểm vẽ ở vị trí/kích thước bạn chỉ định.
Nhược điểm là mặc dù kích thước có thể ở tọa độ dữ liệu, vòng tròn sẽ luôn là một vòng tròn, ngay cả khi tỷ lệ co của ô không phải là 1. (nghĩa là vòng tròn sẽ không căng ra hình trên).
Lợi thế là nó nhanh.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.collections
num = 5000
sizes = 0.4 * np.random.random(num)
xy = 50 * np.random.random((num, 2))
fig, ax = plt.subplots()
coll = matplotlib.collections.EllipseCollection(sizes, sizes,
np.zeros_like(sizes),
offsets=xy, units='x',
transOffset=ax.transData,
**kwargs)
ax.add_collection(coll)
ax.margins(0.01)
plt.show()
Chú ý sự khác biệt khi chúng ta phóng to trên một khu vực tương tự với con số thứ hai. Các vòng tròn trở nên lớn hơn (kích thước nằm trong tọa độ dữ liệu), nhưng vẫn là các vòng tròn thay vì kéo dài. Chúng không phải là biểu diễn chính xác của một vòng tròn trong không gian "dữ liệu".
Để đưa ra một số ý tưởng về sự khác biệt thời gian, đây là thời gian để tạo ra và vẽ một con số với cùng 5000 vòng tròn với nhau trong ba phương pháp:
In [5]: %timeit time_plotting(circles)
1 loops, best of 3: 3.84 s per loop
In [6]: %timeit time_plotting(patch_collection)
1 loops, best of 3: 1.37 s per loop
In [7]: %timeit time_plotting(ellipse_collection)
1 loops, best of 3: 228 ms per loop
Bạn muốn sử dụng một 'EllipseCollection' có thể làm những gì bạn muốn http://matplotlib.org/examples/pylab_examples/ellipse_collection.html – tacaswell