0

Beginner user on the forum. Help please. I have a data set: x, y coordinates, each x, y has a value. I want to plot a 2d histogram displaying the sum of the values in each bin with color scale. matplotlib hexbin is straight forward. I can do this. eg:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LogNorm

xpos = np.random.rand(0,10)
ypos = np.random.rand(0,10)
plt.hexbin(x = xpos, y = ypos, C=mass, cmap= plt.cm.jet, gridsize=100, reduce_C_function=sum, bins="log")  
cb = plt.colorbar()
cb.ax.set_ylabel('log (sum value in each bin)')
plt.xlabel('Xpos')
plt.ylabel('Ypos')
plt.show()

However, I'm struggling to make a similar plot with histogram2d or matplotlib hist2d. I think i have to combine binned_statistic_2d and histogram2d somehow. No problem if I replace plt.hexbin line above to this:

plt.hist2d(x = xpos, y = ypos, bins = 50, norm = LogNorm())

Any clue? I have look on the forum but can't seem to find a working code.

hamster
  • 69
  • 7

1 Answers1

0

You could calculate the values to show in the binned 2D plot prior to plotting and then show as an imshow plot.

If you're happy to use pandas, one option would be to group the mass data accordings to cut (pandas.cut) x and y data. Then apply the sum (.sum()) and unstack to obtain a pivot table.

df.mass.groupby([pd.cut(df.x, bins=xbins, include_lowest=True), 
                 pd.cut(df.y, bins=ybins, include_lowest=True)]) \
               .sum().unstack(fill_value=0)

Here is a complete example:

import numpy as np; np.random.seed(1)
import pandas as pd
import matplotlib.pyplot as plt
import  matplotlib.colors

xpos = np.random.randint(0,10, size=50)
ypos = np.random.randint(0,10, size=50)
mass = np.random.randint(0,75, size=50)

df = pd.DataFrame({"x":xpos, "y":ypos, "mass":mass})

xbins = range(10)
ybins = range(10)
su = df.mass.groupby([pd.cut(df.x, bins=xbins, include_lowest=True), 
                     pd.cut(df.y, bins=ybins, include_lowest=True)]) \
            .sum().unstack(fill_value=0)
print su
im = plt.imshow(su.values, norm=matplotlib.colors.LogNorm(1,300))
plt.xticks(range(len(su.index)), su.index, rotation=90)
plt.yticks(range(len(su.columns)), su.columns)
plt.colorbar(im)
plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712