python एक स्कैटर डेटा सेट का उपयोग कर MatPlotLib में एक हीटमैप उत्पन्न करें




heatmap histogram2d (7)

Seaborn अब संयुक्त प्लॉट समारोह है जो अच्छी तरह से यहां काम करना चाहिए:

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

मेरे पास एक्स, वाई डेटा पॉइंट्स (लगभग 10k) का एक सेट है जो स्कैटर प्लॉट के रूप में साजिश करना आसान है लेकिन मैं एक हीटमैप के रूप में प्रतिनिधित्व करना चाहता हूं।

मैंने MatPlotLib में उदाहरणों को देखा और वे सभी छवि उत्पन्न करने के लिए पहले से ही हीटमैप सेल मानों से शुरू होने लगते हैं।

क्या कोई ऐसी विधि है जो x, y, सभी अलग-अलग, एक हीटमैप में परिवर्तित हो जाती है (जहां x की उच्च आवृत्ति वाले क्षेत्र, y "गर्म" होंगे)?


और प्रारंभिक प्रश्न था ... स्कैटर मानों को ग्रिड मानों में कैसे परिवर्तित करें, है ना? 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

हाँ यहाँ यह और अधिक मुश्किल हो जाता है लेकिन अधिक मजेदार हो जाता है। कुछ पुस्तकालय (क्षमा करें):

from matplotlib import pyplot as plt
from matplotlib import cm
import numpy as np
from scipy.interpolate import griddata

पाइपप्लॉट आज मेरा ग्राफिक इंजन है, सेमी रंगीन मानचित्रों की एक श्रृंखला है जिसमें कुछ अंतर्निहित विकल्प हैं। गणना के लिए numpy, और एक निश्चित ग्रिड को मूल्य संलग्न करने के लिए griddata।

अंतिम एक महत्वपूर्ण है विशेष रूप से क्योंकि xy अंक की आवृत्ति मेरे डेटा में समान रूप से वितरित नहीं होती है। सबसे पहले, आइए मेरे डेटा और मनमाने ढंग से ग्रिड आकार के लिए उपयुक्त कुछ सीमाओं से शुरू करें।

#determine grid boundaries
gridsize = 500
x_min = -8
x_max = 2.5
y_min = -2
y_max = 7

मेरे डेटा में, उच्च ब्याज के क्षेत्र में इस ग्रिड के 500 मूल्यों से बहुत अधिक हैं; जबकि कम ब्याज क्षेत्र में, कुल ग्रिड में अधिकतम 200 मूल्य हैं; x_min और x_max की ग्राफिक सीमाओं के बीच भी कम हैं।

मैं अब अपना ग्रिड परिभाषित करता हूं। प्रत्येक एक्सएक्स-वाई जोड़ी के लिए, मुझे एक रंग चाहिए।

xx = np.linspace(x_min, x_max, gridsize)
yy = np.linspace(y_min, y_max, gridsize)
grid = np.array(np.meshgrid(xx, yy.T))
grid = grid.reshape(2, grid.shape[1]*grid.shape[2]).T

अजीब आकार क्यों? scipy.griddata एक आकार चाहता है (एन, डी)।

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

वी-आकार के बिंदु भाग के आसपास, आप देखते हैं कि मीठी जगह के लिए मेरी खोज के दौरान मेरी बहुत सारी गणनाएं थीं, जबकि लगभग हर जगह कम दिलचस्प हिस्सों में कम संकल्प होता है।


मुझे पता है कि यह एक पुराना सवाल है, लेकिन अलेजांद्रो के एवरर्स को कुछ जोड़ना चाहता था: यदि आप पीई-स्पूवियर का उपयोग किये बिना एक अच्छी चिकनी छवि चाहते हैं तो आप इसके बजाय np.histogram2d उपयोग कर सकते हैं और एक 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()

पैदा करता है:


Np.hist2d का उपयोग करने के बजाय, जो सामान्य रूप से काफी बदसूरत हिस्टोग्राम उत्पन्न करता है, मैं एक अनुकूली चिकनाई कर्नेल का उपयोग करके कण सिमुलेशन को प्रस्तुत करने के लिए एक पायथन पैकेज, 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()

जो निम्नलिखित छवि उत्पन्न करता है:

जैसा कि आप देखते हैं, छवियां बहुत अच्छी लगती हैं, और हम इस पर विभिन्न संरचनाओं की पहचान करने में सक्षम हैं। इन छवियों का निर्माण एक निश्चित डोमेन के भीतर प्रत्येक बिंदु के लिए दिए गए वजन को फैलाने के लिए किया जाता है, जिसे चिकनाई लंबाई से परिभाषित किया जाता है, जो बदले में नज़दीक एनबी पड़ोसी की दूरी से दिया जाता है (मैंने उदाहरणों के लिए 16, 32 और 64 चुना है)। इसलिए, उच्च घनत्व वाले क्षेत्रों आमतौर पर कम घनत्व वाले क्षेत्रों की तुलना में छोटे क्षेत्रों में फैले होते हैं।

फ़ंक्शन माईप्लॉट एक बहुत ही सरल कार्य है जिसे मैंने x, y डेटा को py-sphviewer को जादू करने के लिए लिखा है।


Matplotlib lexicon में, मुझे लगता है कि आप एक हेक्सबिन प्लॉट चाहते हैं।

यदि आप इस प्रकार की साजिश से परिचित नहीं हैं, तो यह केवल एक बिवारिएट हिस्टोग्राम है जिसमें एक्सई-प्लेन हेक्सागोन के नियमित ग्रिड द्वारा टेस्सेल किया जाता है।

तो एक हिस्टोग्राम से, आप केवल प्रत्येक हेक्सागोन में गिरने वाले बिंदुओं की संख्या को गिन सकते हैं, प्लॉटिंग क्षेत्र को खिड़कियों के सेट के रूप में विघटित कर सकते हैं , प्रत्येक बिंदु को इन विंडो में से प्रत्येक को असाइन कर सकते हैं; आखिरकार, खिड़कियों को रंगीन सरणी पर मानचित्र करें, और आपके पास हेक्सबिन आरेख है।

हालांकि उदाहरण, सर्किल या वर्गों से कम सामान्य रूप से उपयोग किया जाता है, लेकिन हेक्सागोन कताई कंटेनर की ज्यामिति के लिए बेहतर विकल्प है सहज ज्ञान युक्त:

  • हेक्सागोन के नजदीकी पड़ोसी समरूपता है (उदाहरण के लिए, स्क्वायर डिब्बे नहीं, उदाहरण के लिए, वर्ग के सीमा पर एक बिंदु से दूरी उस वर्ग के अंदर एक बिंदु तक दूरी हर जगह बराबर नहीं है) और

  • हेक्सागोन उच्चतम एन-पॉलीगॉन है जो नियमित विमान टेस्सेलेशन देता है (यानी, आप हेक्सागोनल के आकार की टाइल के साथ अपने रसोईघर की मंजिल को सुरक्षित रूप से फिर से मॉडल कर सकते हैं क्योंकि आपके पास समाप्त होने पर टाइल्स के बीच कोई शून्य स्थान नहीं होगा - सच नहीं है अन्य सभी उच्च-एन, एन> = 7, बहुभुज)।

( मैटलप्लिब हेक्सबिन प्लॉट शब्द का उपयोग करता है, इसलिए आर (AFAIK) आर के लिए सभी साजिश पुस्तकालयों को करें; फिर भी मुझे नहीं पता कि यह इस प्रकार के भूखंडों के लिए आम तौर पर स्वीकार्य शब्द है, हालांकि मुझे संदेह है कि यह संभव है कि हेक्सबिन छोटा है हेक्सागोनल बिनिंग के लिए , जो प्रदर्शन के लिए डेटा तैयार करने में आवश्यक कदम का वर्णन करता है।)

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


यदि आप 1.2.x का उपयोग कर रहे हैं

x = randn(100000)
y = randn(100000)
hist2d(x,y,bins=100);


एक 2-आयामी सरणी बनाएं जो आपकी अंतिम छवि में कोशिकाओं से मेल खाती है, जिसे heatmap_cells कहते हैं और इसे सभी शून्यों के रूप में heatmap_cells चालू करें।

प्रत्येक आयाम के लिए, वास्तविक इकाइयों में प्रत्येक सरणी तत्व के बीच अंतर को परिभाषित करने वाले दो स्केलिंग कारकों का चयन करें, x_scale और y_scale । इन्हें चुनें कि आपके सभी डेटापॉइंट्स हीटमैप सरणी की सीमाओं के भीतर आ जाएंगे।

x_value और y_value साथ प्रत्येक कच्चे y_value :

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





histogram2d