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




heatmap histogram2d (6)

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

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

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


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 को जादू करने के लिए लिखा है।


एक 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


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

पैदा करता है:


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

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


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


यदि आप हेक्सागोन नहीं चाहते हैं, तो आप 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 कहें, तो आप histogram2d कॉल में bins=(512, 384) डाल सकते हैं।

उदाहरण:





histogram2d