ขนาด hex ใน hexplins matplotlib ขึ้นอยู่กับความหนาแน่นของจุดใกล้เคียง


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'])

กระจัดกระจาย

ฉันทำกราฟข้อมูลโดยใช้ hexbins ดังที่ระบุไว้ด้านล่าง

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

ฉันต้องการเปลี่ยนขนาดของรูปหกเหลี่ยมตามความหนาแน่นของจุดที่พล็อตในพื้นที่ที่รูปหกเหลี่ยมครอบคลุม ตัวอย่างเช่นรูปหกเหลี่ยมที่ด้านล่างซ้าย (จุดที่มีขนาดกะทัดรัด) จะมีขนาดใหญ่กว่ารูปหกเหลี่ยมอื่น ๆ (ที่มีจุดกระจาย) มีวิธีทำเช่นนี้หรือไม่?

แก้ไข: ฉันลองใช้วิธีแก้ปัญหานี้แต่ฉันไม่สามารถหาวิธีทำสีฐานสิบหกตาม df ['Bin'] หรือวิธีตั้งขนาด min และ max hex

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

โซลูชั่นที่นำเสนอ


1
คุณเห็นstackoverflow.com/questions/48844600/หรือไม่?
plasmon360

@ plasmon360 ฉันอัปเดตโพสต์ด้วยงานของฉันจากโซลูชันที่เสนอ
Ethan

1
เมื่อคุณใช้C=df['Bin'],มันจะไม่แสดงความหนาแน่น แต่เป็นปริมาณที่อยู่ในBinคอลัมน์ ดังนั้นพล็อตนั้นถูกต้อง คุณสามารถออกจากการCโต้แย้งและรับขนาดตามความหนาแน่น
ImportanceOfBeingErnest

@ImportanceOfBeingErnest ไม่เป็นไร gotcha ฉันจะทำสีฐานสิบหกด้วย df ['Bin'] ได้อย่างไร ฉันต้องการที่จะสามารถเปลี่ยนขนาด min ของ hexagons ให้ใหญ่ขึ้นอีกเล็กน้อยเป็นไปได้หรือไม่
อีธาน

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']คอลัมน์ได้อย่างไร
อีธาน

คุณไม่ต้องการเห็นความถี่เป็น hexbin แต่รวมผลรวมของค่า df ['Bin']?
หลงทาง

ใช่ฉันต้องการให้สีของรูปหกเหลี่ยมเป็นไปตามdf['Bin']คอลัมน์ดังนั้นฐานหกเหลี่ยมด้านล่างซ้ายจึงเป็นสีฟ้าและสีอื่น ๆ เป็นสีแดง
Ethan

ฉันเพิ่มพล็อตตามผลรวมของ df ['Bins'] คุณสามารถแก้ไข cmap เพื่อจัดการสี ไม่แน่ใจว่าคุณกำลังมองหาที่จะทำอย่างอื่น
หลงทางใน

ฉันไม่ต้องการให้สีตามผลรวมของค่าในถังขยะแทนค่าของถังขยะเอง มีวิธีทำเช่นนั้นหรือไม่? สีจะตรงกับสีในตัวอย่างที่สองของฉัน
Ethan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.