분산 형 데이터 세트를 사용하여 MatPlotLib에서 히트 맵 생성


187

산점도로 플롯하기 쉽지만 히트 맵으로 나타내려는 X, Y 데이터 포인트 (약 10k) 세트가 있습니다.

MatPlotLib의 예제를 살펴본 결과 이미지를 생성하기 위해 이미 히트 맵 셀 값으로 시작하는 것 같습니다.

x, y를 모두 다른 히트 맵으로 변환하는 방법이 있습니까?


답변:


182

육각형을 원하지 않으면 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있습니다.

예: Matplotlib 히트 맵 예


1
나는 바보가 아니라 대화 형 IPython 세션에만 표시하는 대신 실제로 어떻게이 출력을 PNG / PDF 파일로 출력합니까? axes제목, 축 레이블 등을 추가하고 savefig()다른 일반적인 matplotlib 플롯에서와 같이 일반을 수행하는 일종의 일반 인스턴스 로 이것을 얻으려고합니다 .
gotgenes

3
@gotgenes : 작동하지 plt.savefig('filename.png')않습니까? 좌표축 인스턴스를 얻으려면 Matplotlib의 객체 지향 인터페이스를 사용하십시오.fig = plt.figure() ax = fig.gca() ax.imshow(...) fig.savefig(...)
ptomato

1
정말로 감사합니다! 나는 그것이 imshow()같은 범주의 함수에 있다는 것을 완전히 이해하지 못한다고 생각 scatter()합니다. 나는 왜 imshow()2d 배열의 플로트를 적절한 색상의 블록으로 변환 하는지 이해하지 못하는 반면, scatter()그런 배열과 관련하여 무엇을 해야하는지 이해합니다 .
gotgenes

14
imshow를 사용하여 x / y 값의 2d 히스토그램을 플로팅하는 것에 대한 경고 : 기본적으로 imshow는 왼쪽 위 모서리에 원점을 플로팅하고 이미지를 바꿉니다. 산포도와 같은 방향을 얻기 위해 내가해야 할 일은plt.imshow(heatmap.T, extent=extent, origin = 'lower')
Jamie

7
수행하고자하는 사람들을 위해 대수 년 Colorbar이 문제의 볼 stackoverflow.com/questions/17201172/...을 간단하게 할from matplotlib.colors import LogNorm plt.imshow(heatmap, norm=LogNorm()) plt.colorbar()
tommy.carstensen

109

에서 하기 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()   

여기에 이미지 설명을 입력하십시오


"육각형이 가장 가까운 이웃 대칭을 가짐"은 무엇을 의미합니까? 당신은 "사각의 경계에있는 점과 그 정사각형 안에있는 점으로부터의 거리는 어디에나 같지 않다"고 말하지만 무엇에 대한 거리입니까?
Jaan

9
육각형의 경우 두면을 결합하는 중심에서 정점까지의 거리도 측면의 중심에서 중간보다 길지만 비율은 더 작습니다 (육각의 경우 2 / sqrt (3) ≈ 1.15 대 sqrt (2) ≈ 1.41 광장). 중심에서 경계의 모든 지점까지의 거리가 동일한 유일한 모양은 원입니다.
Jaan

5
@ 잔 육각형의 경우 모든 이웃이 같은 거리에 있습니다. 8 이웃 또는 4 이웃에는 문제가 없습니다. 대각선 이웃은 없으며 단지 한 종류의 이웃입니다.
isarandi

@doug gridsize=파라미터를 어떻게 선택합니까? 육각형이 겹치지 않고 닿도록 그렇게 선택하고 싶습니다. 나는 gridsize=100더 작은 육각형을 생산할 것이라는 것을 알았지 만 적절한 가치를 선택하는 방법은 무엇입니까?
Alexander Cska

40

편집 : 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()

결과:

가장 가까운 이웃 스무딩


1
이거 너무 좋아. 그래프는 Alejandro의 답변만큼 훌륭하지만 새로운 패키지는 필요하지 않습니다.
Nathan Clement

아주 좋아요! 그러나이 방법으로 오프셋을 생성합니다. 노멀 스 캐터 그래프와 컬러 그래프를 비교하여이를 확인할 수 있습니다. 수정하기 위해 무언가를 추가 할 수 있습니까? 또는 x 및 y 값으로 그래프를 이동합니까?
Agape Gal'lo

1
아가페 갈로, 오프셋이란 무엇입니까? 서로 위에 플롯하면 일치합니다 (내 게시물 편집 참조). 산란의 너비가 다른 세 가지의 너비와 정확히 일치하지 않기 때문에 아마도 연기되었을 것입니다.
Jurgy

나만을 위해 그래프를 작성해 주셔서 감사합니다! 나는 나의 실수를 이해했다 : 나는 x와 y 한계를 정의하기 위해 "extent"를 수정했다. 이제 그래프의 원점을 수정 한 것으로 알고 있습니다. 그런 다음 마지막 질문이 있습니다. 기존 데이터가없는 영역에서도 어떻게 그래프의 한계를 확장 할 수 있습니까? 예를 들어 x와 y의 경우 -5에서 +5 사이입니다.
Agape Gal'lo

1
x 축이 -5에서 5로, y 축이 -3에서 4로 가고 싶다고 가정 해보십시오. 에 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.
Jurgy

31

일반적으로 상당히 못생긴 히스토그램을 생성하는 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에 제공하여 마법을 수행하기 위해 작성한 매우 간단한 함수입니다.


2
OSX에 py-sphviewer를 설치하려는 사람에 대한 의견 : 꽤 많은 어려움이있었습니다. github.com/alejandrobll/py-sphviewer/issues/3
Sam Finnigan

python3에서는 작동하지 않습니다. 그것은 설치하지만 당신이 그것을 사용하려고하면 다음 ... 충돌
파 비우 디아스

1
@Fabio Dias, 최신 버전 (1.1.x)은 이제 Python 3에서 작동합니다.
Alejandro

29

1.2.x를 사용중인 경우

import numpy as np
import matplotlib.pyplot as plt

x = np.random.randn(100000)
y = np.random.randn(100000)
plt.hist2d(x,y,bins=100)
plt.show()

gaussian_2d_heat_map


17

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()

데모 이미지


간단하고 예쁘고 분석적으로 유용합니다.
ryanjdillon

@words 그래서 어떻게 이것을 사용하여 600k 데이터를 시각적으로 읽을 수있게합니까? (크기 조정 방법)
nrmb

무슨 말인지 잘 모르겠습니다. 별도의 질문을하고 여기에 링크하는 것이 가장 좋습니다. 무화과 전체의 크기를 조정 하시겠습니까? 먼저로 그림을 fig = plt.figure(figsize=(12, 12))만든 다음로 현재 축을 얻은 ax=plt.gca()다음 함수에 인수 ax=ax를 추가하십시오 jointplot.
wordsforthewise

@wordsforthewise 당신은이 질문에 대답하십시오 : stackoverflow.com/questions/50997662/… 감사합니다
ebrahimi 2016 년

4

그리고 초기 질문은 ... 산란 값을 그리드 값으로 변환하는 방법이었습니다. 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_minx_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의 뾰족한 부분 주위에서 스위트 스폿을 검색하는 동안 많은 계산을 수행했지만 거의 모든 곳에서 덜 흥미로운 부분은 해상도가 낮습니다.

고해상도의 SVC 히트 맵


완벽하고 실행 가능한 코드를 갖도록 답변을 향상시킬 수 있습니까? 이것은 당신이 제공 한 흥미로운 방법입니다. 나는 현재 그것을 더 잘 이해하려고 노력하고 있습니다. 왜 V 모양이 있는지 이해가되지 않습니다. 감사.
ldmtwo

V-Shape는 내 데이터에서 비롯됩니다. 그것은 훈련 된 SVM의 f1 값입니다. 이것은 SVM 이론에서 조금 진행되고 있습니다. C가 높으면 계산에 모든 포인트가 포함되어 더 넓은 감마 범위를 사용할 수 있습니다. 감마는 선과 선을 분리하는 곡선의 강성입니다. 이 두 값은 SVM (내 그래픽에서 X와 Y)에 제공되어야합니다. 그런 다음 결과를 얻습니다 (내 그림에서 Z). 가장 좋은 지역에서는 의미있는 높이를 기대할 수 있습니다.
Anderas

두 번째 시도 : V 모양이 내 데이터에 있습니다. SVM의 f1 값입니다. C가 높으면 계산에 모든 포인트가 포함되어 더 넓은 감마 범위가 작동하지만 계산 속도가 느려집니다. 감마는 선과 선을 분리하는 곡선의 강성입니다. 이 두 값은 SVM (내 그래픽에서 X와 Y)에 제공되어야합니다. 그런 다음 결과를 얻습니다 (내 그림에서 Z). 최적화 된 영역에서는 값이 높고 다른 값은 낮습니다. 여기에 표시된 것은 일부 (X, Y)에 대해 Z 값이 있고 다른 곳에 많은 간격이있는 경우 사용할 수 있습니다. (X, Y, Z) 데이터 포인트가 있으면 내 코드를 사용할 수 있습니다.
Anderas

4

여기 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')

1
구현이 매우 비효율적이지만 cKDTree에 대해서는 몰랐습니다. 잘 했어! 내 대답에서 당신을 참조 할 것입니다.
Jurgy

2

최종 이미지의 셀에 해당하는 2 차원 배열을 말하고 heatmap_cells모두 0으로 인스턴스화합니다.

각 차원 실제 단위로 각 배열 요소 사이의 차이를 정의하는 두 개의 스케일링 인자를 선택, 말 x_scaley_scale. 모든 데이터 포인트가 히트 맵 배열의 범위 내에 들어가도록 선택하십시오.

x_value및로 각 원시 데이터 포인트에 대해 y_value:

heatmap_cells[floor(x_value/x_scale),floor(y_value/y_scale)]+=1


1

여기에 이미지 설명을 입력하십시오

다음은 3 가지 범주 (빨간색, 녹색 및 파란색)로 설정된 1 백만 점에서 만든 것입니다. 이 기능을 사용하려면 저장소에 대한 링크가 있습니다. 깃 허브 레포

histplot(
    X,
    Y,
    labels,
    bins=2000,
    range=((-3,3),(-3,3)),
    normalize_each_label=True,
    colors = [
        [1,0,0],
        [0,1,0],
        [0,0,1]],
    gain=50)

0

@Piti의 답변 과 매우 유사 하지만 2 대신 1을 사용하여 포인트를 생성하십시오.

import numpy as np
import matplotlib.pyplot as plt

pts = 1000000
mean = [0.0, 0.0]
cov = [[1.0,0.0],[0.0,1.0]]

x,y = np.random.multivariate_normal(mean, cov, pts).T
plt.hist2d(x, y, bins=50, cmap=plt.cm.jet)
plt.show()

산출:

2d_gaussian_heatmap


0

나는 파티에 조금 늦었 을까 두려워하지만 얼마 전 비슷한 질문이있었습니다. @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)

결과는 다음과 같습니다 여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.