নিকটবর্তী পয়েন্টগুলির ঘনত্বের ভিত্তিতে ম্যাটপ্ল্লোলিব হেক্সবিনে হেক্স আকার


9

আমি নিম্নলিখিত কোড পেয়েছি যা নিম্নলিখিত চিত্র উত্পাদন করে

import numpy as np
np.random.seed(3)
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame()
df['X'] = list(np.random.randint(100, size=100)) + list(np.random.randint(30, size=100))
df['Y'] = list(np.random.randint(100, size=100)) + list(np.random.randint(30, size=100))

df['Bin'] = df.apply(lambda row: .1 if row['X'] < 30 and row['Y'] < 30 else .9, axis=1)

fig, ax = plt.subplots(figsize=(10,10))
plt.scatter(df['X'], df['Y'])

ছিটান

আমি নীচে উল্লিখিত হিসাবে হেক্সবিন ব্যবহার করে ডেটা গ্রাফড করেছি

from matplotlib import cm

fig, ax = plt.subplots(figsize=(10,10))
hexbin = ax.hexbin(df['X'], df['Y'], C=df['Bin'], gridsize=20, cmap= cm.get_cmap('RdYlBu_r'),edgecolors='black')
plt.show()

hexbins

আমি ষড়ভুজ যে অঞ্চলটি coversেকে দিয়েছিল সেগুলিতে প্লট করা পয়েন্টগুলির ঘনত্বের উপর ভিত্তি করে হেক্সাগনগুলির আকার পরিবর্তন করতে চাই। উদাহরণস্বরূপ, নীচে বামে হেক্সাগনগুলি (যেখানে পয়েন্টগুলি সংক্ষিপ্ত রয়েছে) অন্য কোথাও হেক্সাগনগুলির চেয়ে বড় হবে (যেখানে বিন্দুগুলি বিরল)। এই কাজ করতে একটি উপায় আছে কি?

সম্পাদনা: আমি এই সমাধানটি চেষ্টা করেছিলাম , তবে ডিএফ ['বিন'] এর উপর ভিত্তি করে কীভাবে হেক্সেসকে রঙিন করতে হবে, বা ন্যূনতম এবং সর্বাধিক হেক্স আকারটি কীভাবে সেট করবেন তা আমি বুঝতে পারি না।

from matplotlib.collections import PatchCollection
from matplotlib.path import Path
from matplotlib.patches import PathPatch
fig, ax = plt.subplots(figsize=(10,10))
hexbin = ax.hexbin(df['X'], df['Y'], C=df['Bins'], gridsize=20, cmap= cm.get_cmap('RdYlBu_r'),edgecolors='black')
def sized_hexbin(ax,hc):
    offsets = hc.get_offsets()
    orgpath = hc.get_paths()[0]
    verts = orgpath.vertices
    values = hc.get_array()
    ma = values.max()
    patches = []
    for offset,val in zip(offsets,values):
        v1 = verts*val/ma+offset
        path = Path(v1, orgpath.codes)
        patch = PathPatch(path)
        patches.append(patch)

    pc = PatchCollection(patches, cmap=cm.get_cmap('RdYlBu_r'), edgecolors='black')
    pc.set_array(values)
    ax.add_collection(pc)
    hc.remove()

sized_hexbin(ax,hexbin)
plt.show()

প্রস্তাবিত সমাধান



@ plasmon360 আমি প্রস্তাবিত সমাধান থেকে আমার কাজের সাথে পোস্টটি আপডেট করেছি
ইথান

1
আপনি যখন C=df['Bin'],এটি ব্যবহার করবেন তখন ঘনত্বটি প্রদর্শন করা হবে না, বরং Binকলামে পরিমাণ রয়েছে । সুতরাং প্লটটি সঠিক। আপনি Cযুক্তি ছেড়ে দিতে পারেন , এবং ঘনত্বের উপর ভিত্তি করে আকারগুলি পেতে পারেন ।
ImportanceOfBeing

@ ইমপোর্টান্সঅফবিজিং আর্নেষ্ট ঠিক আছে, আছে। আমি কীভাবে ডিএফ ['বিন'] দ্বারা হেক্সেসকে রঙ করতে পারি? আমি আরও একটু বড় হতে হেক্সাগনগুলির ন্যূনতম আকার পরিবর্তন করতে সক্ষম হতে চাই, এটি কি সম্ভব?
ইথান

1
আকারটি val/maকোডের অনুপাতে নির্ধারিত হয় । আপনি যা উপযুক্ত মনে করেন তা দিয়ে এটি প্রতিস্থাপন করতে পারেন। রঙের মাধ্যমে সেট করা হয় pc.set_array(values); আপনি valuesঅবশ্যই অন্য কিছু ব্যবহার করতে পারেন ।
ImportanceOfBeingErnest

উত্তর:


3

রঙ ম্যাপিং বুঝতে আপনি কিছু সময় ব্যয় করতে চাইতে পারেন।

    import numpy as np
    np.random.seed(3)
    import pandas as pd
    import matplotlib.pyplot as plt
    from matplotlib.collections import PatchCollection
    from matplotlib.path import Path
    from matplotlib.patches import PathPatch
    df = pd.DataFrame()
    df['X'] = list(np.random.randint(100, size=100)) + list(np.random.randint(30, size=100))
    df['Y'] = list(np.random.randint(100, size=100)) + list(np.random.randint(30, size=100))

    df['Bin'] = df.apply(lambda row: .1 if row['X'] < 30 and row['Y'] < 30 else .9, axis=1)

    #fig, ((ax1, ax2)) = plt.subplots(1, 2, sharex=True, sharey=True)
    ax1 = plt.scatter(df['X'], df['Y'])

    fig,ax2 = plt.subplots(figsize=(10,10))
    hexbin = ax2.hexbin(df['X'], df['Y'], C=df['Bin'], gridsize=20,edgecolors='black',cmap= 'RdBu', reduce_C_function=np.bincount) #**

    def sized_hexbin(ax,hc):
        offsets = hc.get_offsets()
        orgpath = hc.get_paths()[0]
        verts = orgpath.vertices
        values = hc.get_array()
        ma = values.max()
        patches = []
        for offset,val in zip(offsets,values):
            v1 = verts*val/ma + offset
            path = Path(v1, orgpath.codes)
            patch = PathPatch(path)
            patches.append(patch)

        pc = PatchCollection(patches, cmap= 'RdBu', edgecolors='black')
        pc.set_array(values)

        ax.add_collection(pc)

        hc.remove()

    sized_hexbin(ax2,hexbin)
    cb = plt.colorbar(hexbin, ax=ax2)

    plt.show()

To plot the chart based on df['bins'] values - 

Need to change the reduce_C_function in #** marked line -

    hexbin = ax2.hexbin(df['X'], df['Y'], C=df['Bin'], gridsize=20,edgecolors='black',cmap= 'RdBu', reduce_C_function=np.sum)

[![enter image description here][2]][2]


  [1]: https://i.stack.imgur.com/kv0U4.png
  [2]: https://i.stack.imgur.com/mb0gD.png

# Another variation of the chart :

# Where size is based on count of points in the bins and color is based on values of the df['bin']./ Also added if condition to control minimum hexbin size.


import numpy as np
np.random.seed(3)
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection
from matplotlib.path import Path
from matplotlib.patches import PathPatch
from functools import partial

mycmp = 'coolwarm'

df = pd.DataFrame()
df['X'] = list(np.random.randint(100, size=100)) + list(np.random.randint(30, size=100))
df['Y'] = list(np.random.randint(100, size=100)) + list(np.random.randint(30, size=100))

df['Bin'] = df.apply(lambda row: .1 if row['X'] < 30 and row['Y'] < 30 else .9, axis=1)

#fig, ((ax1, ax2)) = plt.subplots(1, 2, sharex=True, sharey=True)
ax1 = plt.scatter(df['X'], df['Y'])


fig,ax2 = plt.subplots(figsize=(10,10))
hexbin = ax2.hexbin(df['X'], df['Y'], C=df['Bin'], gridsize=15,edgecolors='black',cmap= newcmp , reduce_C_function=np.bincount)
hexbin2 = ax2.hexbin(df['X'], df['Y'], C=df['Bin'], gridsize=15,edgecolors='black',cmap= newcmp , reduce_C_function=np.mean)

def sized_hexbin(ax,hc,hc2):
    offsets = hc.get_offsets()
    orgpath = hc.get_paths()[0]
    verts = orgpath.vertices
    values1 = hc.get_array()
    values2 = hc2.get_array()
    ma = values1.max()
    patches = []

    for offset,val in zip(offsets,values1):
        # Adding condition for minimum size 
        if (val/ma) < 0.2:
            val_t = 0.2
        else:
            val_t = val/ma
        v1 =  verts*val_t + offset
        path = Path(v1, orgpath.codes)
        print(path)
        patch = PathPatch(path)
        patches.append(patch)

    pc = PatchCollection(patches, cmap=  newcmp)  #edgecolors='black'
    pc.set_array(values2)

    ax.add_collection(pc)
    hc.remove()
    hc2.remove()


sized_hexbin(ax2,hexbin,hexbin2)
cb = plt.colorbar(hexbin2, ax=ax2)

plt.xlim((-5, 100))
plt.ylim((-5, 100))

plt.show()

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন


আমি কীভাবে df['Bin']কলামটির উপর ভিত্তি করে রঙ পরিবর্তন করতে পারি ?
এথন

সুতরাং আপনি হেক্সবিনে ফ্রিকোয়েন্সি দেখতে চান না তবে ডিএফ ['বিন'] মানের যোগফল?
21

হ্যাঁ, আমি হেক্সাগনগুলির রঙটি df['Bin']কলামের উপর ভিত্তি করে রাখতে চাই , তাই নীচের বাম হেক্সেসগুলি নীল এবং অন্যগুলি লাল
এথন

আমি df এর যোগফল ['বিনস'] এর ভিত্তিতে প্লট যুক্ত করেছি। আপনি রঙ পরিচালনা করতে cmap সম্পাদনা করতে পারেন। আপনি অন্য কিছু করার চেষ্টা করছেন কিনা তা নিশ্চিত নন।
হারিয়েছি

আমি বিনের মানগুলির পরিবর্তে বিনটির পরিবর্তে মানটির যোগফলের ভিত্তিতে রঙ করতে চাই না। এটা করার কোন উপায় আছে? আমার উদাহরণের দ্বিতীয় প্লটে রঙগুলি রঙের সাথে মিলবে
ইথান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.