回答:
六角形が不要な場合は、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平面が六角形の通常のグリッドによってテッセレーションされている2変量ヒストグラムです。
したがって、ヒストグラムから、各六角形に含まれる点の数を数え、プロット領域を一連のウィンドウとして離散化し、各点をこれらのウィンドウの1つに割り当てることができます。最後に、ウィンドウをカラー配列にマッピングしますと、hexbinダイアグラムが表示されます。
たとえば、円や四角形ほど一般的には使用されていませんが、その六角形はビニングコンテナーのジオメトリに適しています。
六角形は持っている最近傍の対称性を(例えば、正方形のビンにはない、例えば、距離からの正方形の境界上の点にその四角の内側の点はどこにでも等しくない)と
六角形は、通常の平面テッセレーションを提供する最も高いnポリゴンです(つまり、六角形のタイルを使用してキッチンの床を安全に再モデリングできます。これは、完成したときにタイルの間に隙間がないためです。他のすべてのより高いn、n> = 7、ポリゴン)。
(Matplotlibは用語hexbin plotを使用します;(AFAIK)Rのすべてのプロットライブラリを使用します;それでも、これがこのタイプのプロットの一般的に受け入れられている用語であるかどうかはわかりませんが、hexbinが短いと考えられる可能性があります用六角ビニング表示用データを作成における必須のステップを説明しています。)
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の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が重なり合ってプロットされています(クリックすると見やすくなります):
私のガウスフィルターアプローチとアレハンドロのアプローチで私が気付いた1つの違いは、彼の方法が私の構造よりもはるかに優れた局所構造を示すことでした。したがって、ピクセルレベルで単純な最近傍法を実装しました。この方法では、ピクセルごとに距離の逆合計を計算しますn
、データ内の最も近い点のます。この方法は高解像度であり、かなり計算コストがかかりますが、もっと速い方法があると思いますので、改善点がありましたらお知らせください。
更新:私が疑ったように、Scipyを使用したはるかに高速な方法がありscipy.cKDTree
ます。実装については、Gabrielの回答を参照してください。
とにかく、これが私のコードです:
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]])
とforループでは、軸のxとy LIMを設定しますax.set_xlim([-5, 5])
ax.set_ylim([-3, 4])
。さらに、デフォルトでimshow
は、アスペクト比を軸の比率と同じに保ちます(つまり、この例では10:7の比率です)。ただし、プロットウィンドウと一致させる場合は、パラメーターaspect='auto'
をに追加しますimshow
。
一般に非常に醜いヒストグラムを生成するnp.hist2dを使用する代わりに、適応スムージングカーネルを使用してパーティクルシミュレーションをレンダリングするためのpythonパッケージであるpy-sphviewerをリサイクルします。これは、pipから簡単にインストールできます(ウェブページのドキュメントを参照)。例に基づいた次のコードを考えます。
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に渡して魔法をかけるために作成した非常に単純な関数です。
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()
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はいくつかのカラーマップであり、いくつかの選択肢があります。計算用のnumpy、および固定グリッドに値を添付するためのgriddata。
最後の1つは特に重要です。これは、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は、事前定義された方法で、グリッド内のポイントごとに1つの値を計算します。「最も近い」を選択します。空のグリッドポイントは、最も近い隣の値で埋められます。これは、情報が少ない領域のセルが大きいように見えます(そうでない場合でも)。「線形」を補間するように選択すると、情報が少ない領域の鮮明さが低下します。味の問題、本当に。
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シェイプのとがった部分の周りで、スイートスポットの検索中に多くの計算を行いましたが、他のほとんどすべての場所であまり重要でない部分の解像度は低くなっています。
これが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')
これは、3つのカテゴリ(赤、緑、青)の100万ポイントセットで作成したものです。この機能を試してみたい場合は、リポジトリへのリンクを次に示します。Githubレポ
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)
パーティーに少し遅れるのではないかと思いますが、しばらく前に同様の質問がありました。受け入れられた回答(@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)