답변:
육각형을 원하지 않으면 numpy의 histogram2d
함수를 사용할 수 있습니다 .
import numpy as np
import numpy.random
import matplotlib.pyplot as plt
# Generate some test data
x = np.random.randn(8873)
y = np.random.randn(8873)
heatmap, xedges, yedges = np.histogram2d(x, y, bins=50)
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
plt.clf()
plt.imshow(heatmap.T, extent=extent, origin='lower')
plt.show()
이것은 50x50 히트 맵을 만듭니다. 512x384 bins=(512, 384)
와 같은 전화를 원하면에 전화를 걸 수 histogram2d
있습니다.
예:
axes
제목, 축 레이블 등을 추가하고 savefig()
다른 일반적인 matplotlib 플롯에서와 같이 일반을 수행하는 일종의 일반 인스턴스 로 이것을 얻으려고합니다 .
plt.savefig('filename.png')
않습니까? 좌표축 인스턴스를 얻으려면 Matplotlib의 객체 지향 인터페이스를 사용하십시오.fig = plt.figure()
ax = fig.gca()
ax.imshow(...)
fig.savefig(...)
imshow()
같은 범주의 함수에 있다는 것을 완전히 이해하지 못한다고 생각 scatter()
합니다. 나는 왜 imshow()
2d 배열의 플로트를 적절한 색상의 블록으로 변환 하는지 이해하지 못하는 반면, scatter()
그런 배열과 관련하여 무엇을 해야하는지 이해합니다 .
plt.imshow(heatmap.T, extent=extent, origin = 'lower')
from matplotlib.colors import LogNorm
plt.imshow(heatmap, norm=LogNorm())
plt.colorbar()
에서 하기 matplotlib의 어휘, 난 당신이 원하는 생각 hexbin의 플롯을.
이 유형의 플롯에 익숙하지 않은 경우 xy 평면이 규칙적인 육각형 격자로 테셀 레이트 되는 이변 량 히스토그램 일뿐 입니다.
히스토그램에서 각 육각형에 떨어지는 점의 수를 세고, 플로팅 영역을 일련의 창으로 분류하고 , 각 점을이 창 중 하나에 할당 할 수 있습니다. 마지막으로 창을 색상 배열 에 매핑하면 16 진 다이어그램이 나타납니다.
예를 들어 원이나 사각형보다 덜 일반적으로 사용되지만, 육각형이 비닝 컨테이너의 형상에 더 적합한 선택입니다.
육각형이 가장 가까운 이웃 대칭을 (예, 사각형 쓰레기통 예는, 거리가 없습니다 에서 사각형 테두리의 한 점 에 그 사각형 안에 포인트가 사방 같지 않음) 및
육각형은 규칙적인 평면 테셀레이션 을 제공하는 가장 높은 n- 폴리곤입니다. 즉, 완성 된 타일 사이에 빈 공간이 없기 때문에 육각형 타일로 부엌 바닥을 안전하게 리모델링 할 수 있습니다. 다른 모든 더 높은 n, n> = 7, 다각형).
( Matplotlib 은 헥스 빈 플롯 이라는 용어를 사용합니다 . (AFAIK) R에 대한 모든 플로팅 라이브러리도 마찬가지입니다 . 여전히 이것이이 유형의 플롯에 일반적으로 허용되는 용어 인지 는 모르겠지만 헥스 빈이 짧을 것으로 생각됩니다. 위한 육각형 비닝 ,되는 표시 용 데이터를 준비하는 필수 단계를 설명한다.)
from matplotlib import pyplot as PLT
from matplotlib import cm as CM
from matplotlib import mlab as ML
import numpy as NP
n = 1e5
x = y = NP.linspace(-5, 5, 100)
X, Y = NP.meshgrid(x, y)
Z1 = ML.bivariate_normal(X, Y, 2, 2, 0, 0)
Z2 = ML.bivariate_normal(X, Y, 4, 1, 1, 1)
ZD = Z2 - Z1
x = X.ravel()
y = Y.ravel()
z = ZD.ravel()
gridsize=30
PLT.subplot(111)
# if 'bins=None', then color of each hexagon corresponds directly to its count
# 'C' is optional--it maps values to x-y coordinates; if 'C' is None (default) then
# the result is a pure 2D histogram
PLT.hexbin(x, y, C=z, gridsize=gridsize, cmap=CM.jet, bins=None)
PLT.axis([x.min(), x.max(), y.min(), y.max()])
cb = PLT.colorbar()
cb.set_label('mean value')
PLT.show()
gridsize=
파라미터를 어떻게 선택합니까? 육각형이 겹치지 않고 닿도록 그렇게 선택하고 싶습니다. 나는 gridsize=100
더 작은 육각형을 생산할 것이라는 것을 알았지 만 적절한 가치를 선택하는 방법은 무엇입니까?
편집 : Alejandro의 대답을 더 잘 보려면 아래를 참조하십시오.
나는 이것이 오래된 질문이라는 것을 알고 있지만 Alejandro의 anwser에 무언가를 추가하고 싶었습니다 : py-sphviewer를 사용하지 않고 멋진 부드러운 이미지를 원한다면 np.histogram2d
가우스 필터 ( scipy.ndimage.filters
)를 히트 맵에 대신 적용 할 수 있습니다 .
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from scipy.ndimage.filters import gaussian_filter
def myplot(x, y, s, bins=1000):
heatmap, xedges, yedges = np.histogram2d(x, y, bins=bins)
heatmap = gaussian_filter(heatmap, sigma=s)
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
return heatmap.T, extent
fig, axs = plt.subplots(2, 2)
# Generate some test data
x = np.random.randn(1000)
y = np.random.randn(1000)
sigmas = [0, 16, 32, 64]
for ax, s in zip(axs.flatten(), sigmas):
if s == 0:
ax.plot(x, y, 'k.', markersize=5)
ax.set_title("Scatter plot")
else:
img, extent = myplot(x, y, s)
ax.imshow(img, extent=extent, origin='lower', cmap=cm.jet)
ax.set_title("Smoothing with $\sigma$ = %d" % s)
plt.show()
생산 :
아가페 갈로 (Agape Gal'lo)에 대해 서로의 위에 산점도 및 s = 16을 표시했습니다 (더 잘 보려면 클릭).
내가 가우시안 필터 접근 방식과 Alejandro의 접근 방식에서 주목 한 한 가지 차이점은 그의 방법이 로컬 구조를 내 것보다 훨씬 잘 보여주는 것입니다. 따라서 픽셀 수준에서 가장 가까운 가장 가까운 이웃 방법을 구현했습니다. 이 방법은 각 픽셀 n
에 대해 데이터에서 가장 가까운 점 의 거리의 역합을 계산 합니다. 이 방법은 계산 비용이 많이 드는 고해상도이며 더 빠른 방법이 있다고 생각하므로 개선 사항이 있으면 알려주십시오.
업데이트 : 의심 한 것처럼 Scipy 's를 사용하는 훨씬 빠른 방법이 scipy.cKDTree
있습니다. 구현에 대한 가브리엘의 답변 을 참조하십시오 .
어쨌든, 여기 내 코드가 있습니다 :
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
def data_coord2view_coord(p, vlen, pmin, pmax):
dp = pmax - pmin
dv = (p - pmin) / dp * vlen
return dv
def nearest_neighbours(xs, ys, reso, n_neighbours):
im = np.zeros([reso, reso])
extent = [np.min(xs), np.max(xs), np.min(ys), np.max(ys)]
xv = data_coord2view_coord(xs, reso, extent[0], extent[1])
yv = data_coord2view_coord(ys, reso, extent[2], extent[3])
for x in range(reso):
for y in range(reso):
xp = (xv - x)
yp = (yv - y)
d = np.sqrt(xp**2 + yp**2)
im[y][x] = 1 / np.sum(d[np.argpartition(d.ravel(), n_neighbours)[:n_neighbours]])
return im, extent
n = 1000
xs = np.random.randn(n)
ys = np.random.randn(n)
resolution = 250
fig, axes = plt.subplots(2, 2)
for ax, neighbours in zip(axes.flatten(), [0, 16, 32, 64]):
if neighbours == 0:
ax.plot(xs, ys, 'k.', markersize=2)
ax.set_aspect('equal')
ax.set_title("Scatter Plot")
else:
im, extent = nearest_neighbours(xs, ys, resolution, neighbours)
ax.imshow(im, origin='lower', extent=extent, cmap=cm.jet)
ax.set_title("Smoothing over %d neighbours" % neighbours)
ax.set_xlim(extent[0], extent[1])
ax.set_ylim(extent[2], extent[3])
plt.show()
결과:
myplot
기능 추가 range
로 파라미터 np.histogram2d
: np.histogram2d(x, y, bins=bins, range=[[-5, 5], [-3, 4]])
상기 피 루프에서 X 및 Y 축 LIM을 설정 ax.set_xlim([-5, 5])
ax.set_ylim([-3, 4])
. 또한 기본적으로 imshow
종횡비는 축의 비율과 동일하게 유지되므로 (예에서는 10 : 7의 비율) 플롯 창과 일치 시키려면 매개 변수 aspect='auto'
를에 추가하십시오 imshow
.
일반적으로 상당히 못생긴 히스토그램을 생성하는 np.hist2d를 사용하는 대신 , 적응 형 스무딩 커널을 사용하여 입자 시뮬레이션을 렌더링하기위한 python 패키지 인 py-sphviewer 를 재활용하고 싶습니다 . 웹 페이지 설명서를 참조하십시오. 예제를 기반으로하는 다음 코드를 고려하십시오.
import numpy as np
import numpy.random
import matplotlib.pyplot as plt
import sphviewer as sph
def myplot(x, y, nb=32, xsize=500, ysize=500):
xmin = np.min(x)
xmax = np.max(x)
ymin = np.min(y)
ymax = np.max(y)
x0 = (xmin+xmax)/2.
y0 = (ymin+ymax)/2.
pos = np.zeros([3, len(x)])
pos[0,:] = x
pos[1,:] = y
w = np.ones(len(x))
P = sph.Particles(pos, w, nb=nb)
S = sph.Scene(P)
S.update_camera(r='infinity', x=x0, y=y0, z=0,
xsize=xsize, ysize=ysize)
R = sph.Render(S)
R.set_logscale()
img = R.get_image()
extent = R.get_extent()
for i, j in zip(xrange(4), [x0,x0,y0,y0]):
extent[i] += j
print extent
return img, extent
fig = plt.figure(1, figsize=(10,10))
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
# Generate some test data
x = np.random.randn(1000)
y = np.random.randn(1000)
#Plotting a regular scatter plot
ax1.plot(x,y,'k.', markersize=5)
ax1.set_xlim(-3,3)
ax1.set_ylim(-3,3)
heatmap_16, extent_16 = myplot(x,y, nb=16)
heatmap_32, extent_32 = myplot(x,y, nb=32)
heatmap_64, extent_64 = myplot(x,y, nb=64)
ax2.imshow(heatmap_16, extent=extent_16, origin='lower', aspect='auto')
ax2.set_title("Smoothing over 16 neighbors")
ax3.imshow(heatmap_32, extent=extent_32, origin='lower', aspect='auto')
ax3.set_title("Smoothing over 32 neighbors")
#Make the heatmap using a smoothing over 64 neighbors
ax4.imshow(heatmap_64, extent=extent_64, origin='lower', aspect='auto')
ax4.set_title("Smoothing over 64 neighbors")
plt.show()
다음 이미지를 생성합니다.
보시다시피, 이미지는 매우 멋지게 보이고 이미지의 다른 하위 구조를 식별 할 수 있습니다. 이 이미지는 평활화 길이에 의해 정의 된 특정 도메인 내의 모든 포인트에 대해 주어진 가중치를 분산하여 구성되며, 이는 더 가까운 nb 이웃 까지의 거리에 의해 주어진다 (이 예제에서는 16, 32 및 64를 선택 함). 따라서 밀도가 높은 영역은 일반적으로 밀도가 낮은 영역에 비해 작은 영역에 분산됩니다.
myplot 함수는 x, y 데이터를 py-sphviewer에 제공하여 마법을 수행하기 위해 작성한 매우 간단한 함수입니다.
Seaborn은 이제 다음과 같이 훌륭하게 작동 하는 jointplot 기능 을 가지고 있습니다 :
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# Generate some test data
x = np.random.randn(8873)
y = np.random.randn(8873)
sns.jointplot(x=x, y=y, kind='hex')
plt.show()
fig = plt.figure(figsize=(12, 12))
만든 다음로 현재 축을 얻은 ax=plt.gca()
다음 함수에 인수 ax=ax
를 추가하십시오 jointplot
.
그리고 초기 질문은 ... 산란 값을 그리드 값으로 변환하는 방법이었습니다.
histogram2d
셀당 빈도를 계산하지만 셀당 빈도 이외의 다른 데이터가있는 경우 추가 작업이 필요합니다.
x = data_x # between -10 and 4, log-gamma of an svc
y = data_y # between -4 and 11, log-C of an svc
z = data_z #between 0 and 0.78, f1-values from a difficult dataset
그래서 X 및 Y 좌표에 대한 Z 결과가있는 데이터 세트가 있습니다. 그러나 관심 영역 외부의 몇 점 (큰 간격)과 작은 관심 영역의 점 힙을 계산하고있었습니다.
예, 여기서는 더 어려워 지지만 더 재미 있습니다. 일부 라이브러리 (죄송합니다) :
from matplotlib import pyplot as plt
from matplotlib import cm
import numpy as np
from scipy.interpolate import griddata
pyplot은 오늘날 내 그래픽 엔진이며 cm은 initeresting을 선택할 수있는 다양한 색상 맵입니다. 계산을위한 numpy 및 고정 된 그리드에 값을 첨부하기위한 griddata
마지막 것은 xy 포인트의 빈도가 내 데이터에 균등하게 분포되어 있지 않기 때문에 특히 중요합니다. 먼저 내 데이터와 임의의 격자 크기에 맞는 경계로 시작합시다. 원본 데이터에는 해당 x 및 y 경계 외부에도 데이터 포인트가 있습니다.
#determine grid boundaries
gridsize = 500
x_min = -8
x_max = 2.5
y_min = -2
y_max = 7
따라서 x와 y의 최소값과 최대 값 사이에 500 픽셀의 격자를 정의했습니다.
내 데이터에는 높은 관심 분야에서 사용할 수있는 500 개 이상의 값이 있습니다. 낮은 관심 분야에서는 전체 그리드에 200 개의 값이 없습니다. 그래픽 경계 x_min
와 x_max
그 사이 에는 훨씬 적은 수가 있습니다.
멋진 그림을 얻으려면 높은 관심 가치에 대한 평균을 얻고 다른 곳의 차이를 메우는 것이 임무입니다.
이제 그리드를 정의합니다. 각 xx-yy 쌍마다 색상을 원합니다.
xx = np.linspace(x_min, x_max, gridsize) # array of x values
yy = np.linspace(y_min, y_max, gridsize) # array of y values
grid = np.array(np.meshgrid(xx, yy.T))
grid = grid.reshape(2, grid.shape[1]*grid.shape[2]).T
왜 이상한 모양입니까? scipy.griddata 는 (n, D) 모양을 원합니다.
Griddata는 미리 정의 된 방법으로 그리드의 포인트 당 하나의 값을 계산합니다. "가장 가까운"을 선택합니다. 빈 그리드 포인트는 가장 가까운 이웃의 값으로 채워집니다. 이것은 정보가 적은 영역이 셀이 더 큰 것처럼 보입니다 (그렇지 않은 경우에도). "선형"을 보간하도록 선택할 수 있으며 정보가 적은 영역은 덜 선명 해 보입니다. 정말로 맛의 문제.
points = np.array([x, y]).T # because griddata wants it that way
z_grid2 = griddata(points, z, grid, method='nearest')
# you get a 1D vector as result. Reshape to picture format!
z_grid2 = z_grid2.reshape(xx.shape[0], yy.shape[0])
그리고 홉, 우리는 음모를 표시하기 위해 matplotlib로 넘겨줍니다.
fig = plt.figure(1, figsize=(10, 10))
ax1 = fig.add_subplot(111)
ax1.imshow(z_grid2, extent=[x_min, x_max,y_min, y_max, ],
origin='lower', cmap=cm.magma)
ax1.set_title("SVC: empty spots filled by nearest neighbours")
ax1.set_xlabel('log gamma')
ax1.set_ylabel('log C')
plt.show()
V-Shape의 뾰족한 부분 주위에서 스위트 스폿을 검색하는 동안 많은 계산을 수행했지만 거의 모든 곳에서 덜 흥미로운 부분은 해상도가 낮습니다.
여기 Jurgy의 가장 가까운 좋은 이웃 방식 만 사용하여 구현 scipy.cKDTree을 . 내 테스트에서는 약 100 배 빠릅니다.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from scipy.spatial import cKDTree
def data_coord2view_coord(p, resolution, pmin, pmax):
dp = pmax - pmin
dv = (p - pmin) / dp * resolution
return dv
n = 1000
xs = np.random.randn(n)
ys = np.random.randn(n)
resolution = 250
extent = [np.min(xs), np.max(xs), np.min(ys), np.max(ys)]
xv = data_coord2view_coord(xs, resolution, extent[0], extent[1])
yv = data_coord2view_coord(ys, resolution, extent[2], extent[3])
def kNN2DDens(xv, yv, resolution, neighbours, dim=2):
"""
"""
# Create the tree
tree = cKDTree(np.array([xv, yv]).T)
# Find the closest nnmax-1 neighbors (first entry is the point itself)
grid = np.mgrid[0:resolution, 0:resolution].T.reshape(resolution**2, dim)
dists = tree.query(grid, neighbours)
# Inverse of the sum of distances to each grid point.
inv_sum_dists = 1. / dists[0].sum(1)
# Reshape
im = inv_sum_dists.reshape(resolution, resolution)
return im
fig, axes = plt.subplots(2, 2, figsize=(15, 15))
for ax, neighbours in zip(axes.flatten(), [0, 16, 32, 63]):
if neighbours == 0:
ax.plot(xs, ys, 'k.', markersize=5)
ax.set_aspect('equal')
ax.set_title("Scatter Plot")
else:
im = kNN2DDens(xv, yv, resolution, neighbours)
ax.imshow(im, origin='lower', extent=extent, cmap=cm.Blues)
ax.set_title("Smoothing over %d neighbours" % neighbours)
ax.set_xlim(extent[0], extent[1])
ax.set_ylim(extent[2], extent[3])
plt.savefig('new.png', dpi=150, bbox_inches='tight')
나는 파티에 조금 늦었 을까 두려워하지만 얼마 전 비슷한 질문이있었습니다. @ptomato의 답변이 도움이되었지만 누군가에게 유용 할 경우를 대비하여 게시하고 싶습니다.
''' I wanted to create a heatmap resembling a football pitch which would show the different actions performed '''
import numpy as np
import matplotlib.pyplot as plt
import random
#fixing random state for reproducibility
np.random.seed(1234324)
fig = plt.figure(12)
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
#Ratio of the pitch with respect to UEFA standards
hmap= np.full((6, 10), 0)
#print(hmap)
xlist = np.random.uniform(low=0.0, high=100.0, size=(20))
ylist = np.random.uniform(low=0.0, high =100.0, size =(20))
#UEFA Pitch Standards are 105m x 68m
xlist = (xlist/100)*10.5
ylist = (ylist/100)*6.5
ax1.scatter(xlist,ylist)
#int of the co-ordinates to populate the array
xlist_int = xlist.astype (int)
ylist_int = ylist.astype (int)
#print(xlist_int, ylist_int)
for i, j in zip(xlist_int, ylist_int):
#this populates the array according to the x,y co-ordinate values it encounters
hmap[j][i]= hmap[j][i] + 1
#Reversing the rows is necessary
hmap = hmap[::-1]
#print(hmap)
im = ax2.imshow(hmap)