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


187

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

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

क्या कोई ऐसा तरीका है जो x, y, के सभी समूहों को एक हीटमैप में परिवर्तित करता है (जहां 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()सकता हूं जैसे मैं किसी अन्य विशिष्ट मैटलपोटलिब प्लॉट के लिए करूंगा।
गत

3
@ वार्ता: काम नहीं plt.savefig('filename.png')करता है? यदि आप एक कुल्हाड़ी उदाहरण प्राप्त करना चाहते हैं, तो Matplotlib के ऑब्जेक्ट-ओरिएंटेड इंटरफ़ेस का उपयोग करें:fig = plt.figure() ax = fig.gca() ax.imshow(...) fig.savefig(...)
ptomato

1
वास्तव में, धन्यवाद! मुझे लगता है कि मुझे पूरी तरह से समझ में नहीं आता है कि imshow()कार्यों की एक ही श्रेणी पर है scatter()। मुझे ईमानदारी से समझ में नहीं आता कि imshow()उपयुक्त रंग के ब्लॉक में फ़्लोट्स के 2d सरणी को क्यों परिवर्तित किया जाता है, जबकि मुझे समझ में नहीं आता कि scatter()इस तरह के एरे के साथ क्या करना चाहिए।
जन्म

14
इस तरह से x / y मान के 2d हिस्टोग्राम की साजिश रचने के लिए imshow का उपयोग करने के बारे में एक चेतावनी: डिफ़ॉल्ट रूप से, imshow ऊपरी बाएं कोने में मूल को प्लॉट करता है और छवि को स्थानांतरित करता है। स्कैटर प्लॉट के समान ओरिएंटेशन पाने के लिए मैं क्या करूंगाplt.imshow(heatmap.T, extent=extent, origin = 'lower')
जेमी

7
एक लघुगणक from matplotlib.colors import LogNorm plt.imshow(heatmap, norm=LogNorm()) plt.colorbar()
रंग पट्टी

109

में matplotlib शब्दकोश, मुझे लगता है कि आप एक चाहते hexbin साजिश।

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

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

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

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

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

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


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

यहां छवि विवरण दर्ज करें


इसका क्या मतलब है कि "हेक्सागोन्स में निकटतम-पड़ोसी समरूपता है"? आप कहते हैं कि "एक वर्ग की सीमा पर एक बिंदु से दूरी और उस वर्ग के अंदर एक बिंदु हर जगह समान नहीं है" लेकिन दूरी क्या है?
जान

9
एक षट्भुज के लिए, केंद्र से दो तरफ जुड़ने वाली एक शीर्ष से दूरी भी केंद्र से एक पक्ष के मध्य तक लंबी होती है, केवल अनुपात छोटा होता है (2 / sqrt (3) for 1.15 षट्भुज बनाम sqrt (2) 41 1.41 के लिए वर्ग के लिए)। एकमात्र आकार जहां सीमा पर केंद्र से हर बिंदु की दूरी समान है।
जान

5
@ जान एक षट्भुज के लिए, प्रत्येक पड़ोसी समान दूरी पर है। 8-पड़ोस या 4-पड़ोस के साथ कोई समस्या नहीं है। कोई विकर्ण पड़ोसी नहीं, सिर्फ एक प्रकार का पड़ोसी।
इसरांडी

@doug आप gridsize=पैरामीटर का चयन कैसे करते हैं मैं इसे ऐसे चुनना चाहूंगा, ताकि हेक्सागोन्स बिना ओवरलैपिंग के सिर्फ स्पर्श करें। मैंने देखा कि gridsize=100छोटे हेक्सागोन्स का उत्पादन होगा, लेकिन उचित मूल्य कैसे चुनें?
अलेक्जेंडर सेस्का

40

संपादित करें: एलेजांद्रो के उत्तर के बेहतर सन्निकटन के लिए, नीचे देखें।

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

एक दूसरे के ऊपर


एक अंतर जो मैंने अपने गाऊसी फिल्टर दृष्टिकोण और अलेजांद्रो के दृष्टिकोण के साथ देखा, वह यह था कि उनका तरीका स्थानीय संरचनाओं को खान से बेहतर दिखाता है। इसलिए मैंने पिक्सेल स्तर पर एक सरल निकटतम पड़ोसी विधि लागू की। यह विधि प्रत्येक पिक्सेल के लिए दूरी की व्युत्क्रम राशि की गणना करती हैn लिए डेटा में निकटतम बिंदुओं । यह विधि एक उच्च रिज़ॉल्यूशन पर है जो कम्प्यूटेशनल रूप से बहुत महंगा है और मुझे लगता है कि इसका एक तेज़ तरीका है, इसलिए मुझे बताएं कि क्या आपके पास कोई सुधार है।

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

बहुत अच्छा ! लेकिन आप इस विधि से एक ऑफसेट उत्पन्न करते हैं। आप इसे रंगीन के साथ एक सामान्य तितर बितर ग्राफ की तुलना करके देख सकते हैं। क्या आप इसे सही करने के लिए कुछ जोड़ सकते हैं? या सिर्फ x और y मानों द्वारा ग्राफ को स्थानांतरित करने के लिए?
अगपे गालो

1
Agape Gal'lo, ऑफसेट से आपका क्या अभिप्राय है? यदि आप उन्हें प्रत्येक मैच के ऊपर प्लॉट करते हैं तो वे मिलान करते हैं (मेरी पोस्ट का संपादन देखें)। शायद आप बंद कर रहे हैं क्योंकि तितर बितर की चौड़ाई अन्य तीन के साथ बिल्कुल मेल नहीं खाती है।
जूगी

बस मेरे लिए ग्राफ की साजिश रचने के लिए बहुत बहुत धन्यवाद! मुझे अपनी गलती समझ में आई: मैंने एक्स और वाई सीमा को परिभाषित करने के लिए "हद" को संशोधित किया था। अब मैं समझता हूँ कि इसने ग्राफ़ की उत्पत्ति को संशोधित किया है। फिर, मेरे पास एक आखिरी सवाल है: मैं ग्राफ़ की सीमा का विस्तार कैसे कर सकता हूं, यहां तक ​​कि उस क्षेत्र के लिए भी जहां मौजूदा डेटा नहीं हैं? उदाहरण के लिए, x और y के लिए -5 से +5 के बीच।
अगपे गालो

1
कहते हैं कि आप x अक्ष को -5 से 5 पर और y अक्ष को -3 से 4 तक जाना चाहते हैं; में myplotसमारोह, जोड़ने rangeके लिए पैरामीटर np.histogram2d: np.histogram2d(x, y, bins=bins, range=[[-5, 5], [-3, 4]])और के लिए लूप में एक्स और अक्ष के y लिम सेट: ax.set_xlim([-5, 5]) ax.set_ylim([-3, 4])। इसके अतिरिक्त, डिफ़ॉल्ट रूप से, imshowआपके अक्षों के अनुपात के समान पहलू अनुपात रखता है (इसलिए मेरे उदाहरण में 10: 7 का अनुपात), लेकिन यदि आप चाहते हैं कि यह आपके प्लॉट विंडो से मेल खाए, तो पैरामीटर aspect='auto'को इसमें जोड़ें imshow
जुर्जी

31

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

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

यहां छवि विवरण दर्ज करें

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

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


2
OSX पर py-sphviewer स्थापित करने की कोशिश कर रहे किसी के लिए एक टिप्पणी: मुझे काफी कठिनाई हुई, देखें: github.com/alejandrobll/py-sphviewer/issues/3
सैम फिननिगन

बहुत बुरा यह python3 के साथ काम नहीं करता है। यह स्थापित होता है, लेकिन तब क्रैश हो जाता है जब आप इसका उपयोग करने का प्रयास करते हैं ...
फ़ेबियो डायस

1
@ फैबियो डायस, नवीनतम संस्करण (1.1.x) अब पायथन 3 के साथ काम करता है
एलेजांद्रो


17

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

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

डेमो छवि


सरल, सुंदर और विश्लेषणात्मक रूप से उपयोगी।
रैंजडिलन

@wordsforthewise आप इसका उपयोग करके 600k डेटा नेत्रहीन कैसे पढ़ सकते हैं? (कैसे आकार बदलने के लिए)
nrmb

मुझे पूरा यकीन नहीं है कि आपका क्या मतलब है; शायद यह सबसे अच्छा है कि आप एक अलग सवाल पूछें और इसे यहां लिंक करें। आप पूरे अंजीर का आकार बदलते हैं? सबसे पहले साथ आंकड़ा बनाने के fig = plt.figure(figsize=(12, 12))लिए, तो साथ वर्तमान अक्ष मिलता ax=plt.gca()है, तो तर्क जोड़ने ax=axके लिए jointplotकार्य करते हैं।
शब्दफिरवाइज

@wordsforthewise क्या आप इस प्रश्न का उत्तर दे सकते हैं: stackoverflow.com/questions/50997662/… धन्यवाद
Ebrahimi

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-results वाला डेटासेट है। हालांकि, मैं ब्याज के क्षेत्र (बड़े अंतराल) के बाहर कुछ बिंदुओं की गणना कर रहा था, और ब्याज के एक छोटे से क्षेत्र में अंकों के ढेर।

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

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

pyplot आज मेरा ग्राफिक इंजन है, सेमी कुछ रंग भरने वाले विकल्पों के साथ रंगीन मानचित्रों की एक श्रृंखला है। एक निश्चित ग्रिड के लिए मूल्यों को संलग्न करने के लिए गणना के लिए सुन्न, और 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_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) का एक आकार चाहता है।

ग्रिडिडा पूर्वनिर्धारित विधि द्वारा ग्रिड में प्रति बिंदु एक मान की गणना करता है। मैं "निकटतम" चुनता हूं - खाली ग्रिड अंक निकटतम पड़ोसी से मूल्यों से भरा होगा। ऐसा लगता है कि कम जानकारी वाले क्षेत्रों में बड़ी कोशिकाएं हैं (भले ही ऐसा न हो)। एक "रैखिक" को प्रक्षेपित करने का विकल्प चुन सकता है, फिर कम जानकारी वाले क्षेत्र कम तेज दिखते हैं। स्वाद की बात, सच में।

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

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

उच्च संकल्प में एक एसवीसी के हीटमैप


क्या आप अपने जवाब को पूर्ण और चलाने योग्य कोड में सुधार कर सकते हैं? यह एक दिलचस्प विधि है जिसे आपने प्रदान किया है। मैं इसे बेहतर ढंग से समझने की कोशिश कर रहा हूं। मुझे समझ में नहीं आता है कि वी आकार क्यों है। धन्यवाद।
ldmtwo

वी-शेप मेरे डेटा से आता है। यह एक प्रशिक्षित एसवीएम के लिए एफ 1-मूल्य है: यह एसवीएम के सिद्धांत में थोड़ा सा चल रहा है। यदि आपके पास उच्च सी है, तो इसमें गणना में आपके सभी बिंदु शामिल हैं, जिससे एक व्यापक गामा रेंज काम करने की अनुमति देता है। गामा कर्व की कठोरता है जो अच्छे और बुरे को अलग करती है। उन दो मूल्यों को एसवीएम (मेरे ग्राफिक में एक्स और वाई) को दिया जाना है; तब आपको एक परिणाम मिलता है (Z मेरे ग्राफिक में)। सबसे अच्छे क्षेत्र में आप सार्थक ऊंचाइयों की आशा करते हैं।
एंड्रियास

दूसरी कोशिश: वी-शेप मेरे डेटा में है। यह एसवीएम के लिए f1- मूल्य है: यदि आपके पास उच्च सी है, तो इसमें गणना में आपके सभी बिंदु शामिल हैं, काम करने के लिए एक व्यापक गामा रेंज की अनुमति है, लेकिन गणना धीमी बना रही है। गामा कर्व की कठोरता है जो अच्छे और बुरे को अलग करती है। उन दो मूल्यों को एसवीएम (मेरे ग्राफिक में एक्स और वाई) को दिया जाना है; तब आपको एक परिणाम मिलता है (Z मेरे ग्राफिक में)। अनुकूलित क्षेत्र में आपको उच्च मूल्य, कहीं और कम मूल्य मिलते हैं। यदि आपने कुछ (X, Y) और अन्य अंतरालों के लिए Z-मान रखा है, तो मैंने यहां जो दिखाया वह प्रयोग करने योग्य है। यदि आपके पास (X, Y, Z) डेटापॉइंट हैं, तो आप मेरे कोड का उपयोग कर सकते हैं।
एंड्रियास 22'18

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 के बारे में नहीं जानता था। बहुत बढ़िया! मैं अपने उत्तर में आपका संदर्भ लूंगा।
जूरी

2

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

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

प्रत्येक कच्चे डाटापॉइंट के साथ x_valueऔर y_value:

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


1

यहां छवि विवरण दर्ज करें

यहां मैं एक 1 मिलियन पॉइंट पर बना हूं जो 3 श्रेणियों (रंगीन लाल, हरा और नीला) के साथ सेट है। यदि आप फ़ंक्शन को आज़माना चाहते हैं तो यहां रिपॉजिटरी का लिंक दिया गया है। गितुब रेपो

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)

यहाँ परिणाम है यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.