Saya memiliki satu set data X, Y poin (sekitar 10k) yang mudah untuk plot sebagai sebar plot tetapi saya ingin mewakili sebagai peta panas.
Saya melihat contoh-contoh di MatPlotLib dan semuanya tampaknya sudah mulai dengan nilai sel heatmap untuk menghasilkan gambar.
Apakah ada metode yang mengubah sekelompok x, y, semuanya berbeda, menjadi peta panas (di mana zona dengan frekuensi x yang lebih tinggi, y akan menjadi "lebih hangat")?
python
matplotlib
heatmap
histogram2d
greye
sumber
sumber
Jawaban:
Jika Anda tidak ingin hexagon, Anda dapat menggunakan
histogram2d
fungsi numpy :Ini menghasilkan peta panas 50x50. Jika Anda ingin, katakanlah, 512x384, Anda dapat melakukan
bins=(512, 384)
panggilan kehistogram2d
.Contoh:
sumber
axes
contoh normal , di mana saya dapat menambahkan judul, label sumbu, dll dan kemudian melakukan yang normalsavefig()
seperti yang akan saya lakukan untuk plot matplotlib khas lainnya.plt.savefig('filename.png')
berfungsi? Jika Anda ingin mendapatkan contoh sumbu, gunakan antarmuka berorientasi objekfig = plt.figure()
ax = fig.gca()
ax.imshow(...)
fig.savefig(...)
imshow()
ada pada kategori fungsi yang sama denganscatter()
. Jujur saya tidak mengerti mengapaimshow()
mengubah array 2d mengapung menjadi blok warna yang sesuai, sedangkan saya mengerti apascatter()
yang harus dilakukan dengan array seperti itu.plt.imshow(heatmap.T, extent=extent, origin = 'lower')
from matplotlib.colors import LogNorm
plt.imshow(heatmap, norm=LogNorm())
plt.colorbar()
Dalam leksikon Matplotlib , saya pikir Anda ingin plot hexbin .
Jika Anda tidak terbiasa dengan jenis plot ini, itu hanya histogram bivariat di mana xy-plane di-tellellated oleh kisi-kisi segi enam biasa.
Jadi dari histogram, Anda bisa menghitung jumlah titik yang jatuh di setiap segi enam, diskritkan wilayah plot sebagai satu set jendela , tetapkan setiap titik ke salah satu jendela ini; akhirnya, petakan windows ke array warna , dan Anda punya diagram hexbin.
Meskipun lebih jarang digunakan daripada misalnya, lingkaran, atau kuadrat, hexagon adalah pilihan yang lebih baik untuk geometri wadah binning intuitif:
segi enam memiliki simetri tetangga terdekat (mis., kotak persegi tidak, misalnya, jarak dari titik di perbatasan kotak ke titik di dalam kotak itu tidak sama di mana-mana) dan
hexagon adalah n-poligon tertinggi yang memberikan tessellation bidang reguler (yaitu, Anda dapat dengan aman memodel ulang lantai dapur Anda dengan ubin berbentuk heksagonal karena Anda tidak akan memiliki ruang kosong antara ubin ketika Anda selesai - tidak berlaku untuk semua lainnya yang lebih tinggi-n, n> = 7, poligon).
( Matplotlib menggunakan istilah heksbin plot; demikian juga (AFAIK) semua perpustakaan petak untuk R ; masih saya tidak tahu apakah ini istilah yang diterima secara umum untuk plot jenis ini, meskipun saya curiga ada kemungkinan bahwa hexbin pendek. untuk heksagonal binning , yang menggambarkan langkah penting dalam menyiapkan data untuk ditampilkan.)
sumber
gridsize=
parameter. Saya ingin memilihnya sedemikian rupa, sehingga segi enam hanya menyentuh tanpa tumpang tindih. Saya perhatikan bahwagridsize=100
akan menghasilkan hexagon yang lebih kecil, tetapi bagaimana cara memilih nilai yang tepat?Sunting: Untuk perkiraan jawaban Alejandro yang lebih baik, lihat di bawah.
Saya tahu ini adalah pertanyaan lama, tetapi ingin menambahkan sesuatu ke server Alejandro: Jika Anda ingin gambar yang dihaluskan tanpa menggunakan py-sphviewer, Anda dapat menggunakan
np.histogram2d
dan menerapkan filter gaussian (dariscipy.ndimage.filters
) ke peta panas:Menghasilkan:
Plot sebar dan s = 16 diplot di atas satu sama lain untuk Agape Gal'lo (klik untuk tampilan yang lebih baik):
Satu perbedaan yang saya perhatikan dengan pendekatan filter gaussian saya dan pendekatan Alejandro adalah bahwa metodenya menunjukkan struktur lokal jauh lebih baik daripada milik saya. Oleh karena itu saya menerapkan metode tetangga terdekat yang sederhana di tingkat piksel. Metode ini menghitung untuk setiap piksel jumlah terbalik dari jarak
n
titik terdekat dalam data. Metode ini pada resolusi tinggi komputasi yang cukup mahal dan saya pikir ada cara yang lebih cepat, jadi beri tahu saya jika Anda memiliki perbaikan.Pembaruan: Seperti yang saya duga, ada metode yang jauh lebih cepat menggunakan Scipy's
scipy.cKDTree
. Lihat jawaban Gabriel untuk implementasinya.Bagaimanapun, ini kode saya:
Hasil:
sumber
myplot
fungsi, menambahkanrange
parameter kenp.histogram2d
:np.histogram2d(x, y, bins=bins, range=[[-5, 5], [-3, 4]])
dan dalam untuk loop mengatur x dan y lim sumbu:ax.set_xlim([-5, 5])
ax.set_ylim([-3, 4])
. Selain itu, secara default,imshow
menjaga rasio aspek identik dengan rasio sumbu Anda (jadi dalam contoh saya rasio 10: 7), tetapi jika Anda ingin agar sesuai dengan jendela plot Anda, tambahkan parameteraspect='auto'
keimshow
.Alih-alih menggunakan np.hist2d, yang secara umum menghasilkan histogram yang sangat jelek, saya ingin mendaur ulang py-sphviewer , paket python untuk rendering simulasi partikel menggunakan kernel smoothing adaptive dan yang dapat dengan mudah dipasang dari pip (lihat dokumentasi halaman web). Pertimbangkan kode berikut, yang didasarkan pada contoh:
yang menghasilkan gambar berikut:
Seperti yang Anda lihat, gambar terlihat cukup bagus, dan kami dapat mengidentifikasi berbagai substruktur di atasnya. Gambar-gambar ini dibangun menyebarkan bobot yang diberikan untuk setiap titik dalam domain tertentu, ditentukan oleh panjang smoothing, yang pada gilirannya diberikan oleh jarak ke tetangga nb lebih dekat (saya telah memilih 16, 32 dan 64 untuk contoh). Jadi, daerah dengan kepadatan lebih tinggi biasanya tersebar di daerah yang lebih kecil dibandingkan dengan daerah dengan kepadatan lebih rendah.
Fungsi myplot hanyalah fungsi yang sangat sederhana yang saya tulis untuk memberikan data x, y ke py-sphviewer untuk melakukan keajaiban.
sumber
Jika Anda menggunakan 1.2.x
sumber
Seaborn sekarang memiliki fungsi jointplot yang seharusnya bekerja dengan baik di sini:
sumber
fig = plt.figure(figsize=(12, 12))
, kemudian dapatkan sumbu saat iniax=plt.gca()
, kemudian tambahkan argumenax=ax
kejointplot
fungsi.dan pertanyaan awal adalah ... bagaimana cara mengubah nilai sebar ke nilai kotak, kan?
histogram2d
tidak menghitung frekuensi per sel, namun, jika Anda memiliki data lain per sel dari hanya frekuensi, Anda akan memerlukan beberapa pekerjaan tambahan untuk dilakukan.Jadi, saya punya dataset dengan hasil-Z untuk koordinat X dan Y. Namun, saya menghitung beberapa poin di luar bidang minat (kesenjangan besar), dan banyak poin di bidang minat kecil.
Ya di sini menjadi lebih sulit tetapi juga lebih menyenangkan. Beberapa perpustakaan (maaf):
pyplot adalah mesin grafis saya hari ini, cm adalah berbagai peta warna dengan beberapa pilihan initeresting. numpy untuk perhitungan, dan data grid untuk melampirkan nilai ke jaringan tetap.
Yang terakhir ini penting terutama karena frekuensi titik xy tidak terdistribusi secara merata dalam data saya. Pertama, mari kita mulai dengan beberapa batasan yang cocok dengan data saya dan ukuran kisi yang berubah-ubah. Data asli memiliki titik data juga di luar batas x dan y.
Jadi kami telah mendefinisikan kisi dengan 500 piksel antara nilai min dan maks x dan y.
Dalam data saya, ada lebih dari 500 nilai yang tersedia di bidang minat tinggi; sedangkan di bidang berbunga rendah, tidak ada bahkan 200 nilai dalam total grid; antara batas-batas grafis
x_min
danx_max
bahkan ada lebih sedikit.Jadi untuk mendapatkan gambar yang bagus, tugasnya adalah untuk mendapatkan rata-rata nilai bunga tinggi dan mengisi celah di tempat lain.
Saya mendefinisikan grid saya sekarang. Untuk setiap pasangan xx-yy, saya ingin memiliki warna.
Kenapa bentuknya aneh? scipy.griddata menginginkan bentuk (n, D).
Griddata menghitung satu nilai per titik di grid, dengan metode yang telah ditentukan. Saya memilih "terdekat" - titik grid kosong akan diisi dengan nilai dari tetangga terdekat. Ini terlihat seolah-olah area dengan informasi yang lebih sedikit memiliki sel yang lebih besar (bahkan jika bukan itu masalahnya). Seseorang dapat memilih untuk menginterpolasi "linear", maka area dengan informasi yang lebih sedikit terlihat kurang tajam. Soal rasa, kok.
Dan hop, kami serahkan ke matplotlib untuk menampilkan plot
Di sekitar bagian runcing dari V-Shape, Anda tahu saya melakukan banyak perhitungan selama pencarian saya untuk sweet spot, sedangkan bagian yang kurang menarik hampir di tempat lain memiliki resolusi lebih rendah.
sumber
Inilah pendekatan tetangga terdekat Jurgy yang hebat tetapi diimplementasikan menggunakan scipy.cKDTree . Dalam pengujian saya sekitar 100x lebih cepat.
sumber
Buat array 2 dimensi yang sesuai dengan sel-sel di gambar akhir Anda, disebut say
heatmap_cells
dan instantiate sebagai semua nol.Pilih dua faktor penskalaan yang menentukan perbedaan antara setiap elemen array dalam unit nyata, untuk setiap dimensi, katakan
x_scale
dany_scale
. Pilih ini sedemikian rupa sehingga semua titik data Anda akan berada dalam batas array peta panas.Untuk setiap titik data mentah dengan
x_value
dany_value
:heatmap_cells[floor(x_value/x_scale),floor(y_value/y_scale)]+=1
sumber
Inilah yang saya buat pada set 1 Juta titik dengan 3 kategori (berwarna Merah, Hijau, dan Biru). Berikut ini tautan ke repositori jika Anda ingin mencoba fungsinya. Github Repo
sumber
Sangat mirip dengan jawaban @ Piti , tetapi menggunakan 1 panggilan alih-alih 2 untuk menghasilkan poin:
Keluaran:
sumber
Saya khawatir saya sedikit terlambat ke pesta tetapi saya memiliki pertanyaan serupa beberapa waktu lalu. Jawaban yang diterima (oleh @ptomato) membantu saya, tetapi saya juga ingin memposting ini jika itu berguna untuk seseorang.
Inilah hasilnya
sumber