簡體   English   中英

使用 Python 在 3D 軸上繪制直方圖

[英]Plotting histograms on 3D axes with Python

I am trying to plot a few histograms on a 3d axis using the PolyCollection function, my desired plot looks something like this: (except of course the coloured plots are histograms) 在此處輸入圖像描述

對我來說,我的 x 值是參數 C_l 的值的分布,y 值是 l 的值(范圍從 2 到 33),z 是每個 C_l 的頻率(所以直方圖在 xz 平面上, y 為 l) 的每個值指定直方圖。 這是我擁有的代碼,但我似乎無法讓它工作:

fig = plt.figure()
ax = fig.gca(projection='3d')
nside=16

'multi_dens_auto_cl_dist is just a 33x1001 matrix of all the C_l values, with the rows denoting each iteration I calculated previously and the columns being the l's)
xs=np.linspace(multi_dens_auto_cl_dist.min(),multi_dens_auto_cl_dist.max(),num=1001)

def cc(arg):
    return mcolors.to_rgba(arg, alpha=0.6)

verts = []
zs = np.arange(2,2*nside+1,1)

for z in zs:
    ys,binvals,_ = plt.hist(multi_dens_auto_cl_dist[:][z],bins=xs)
    ys[0], ys[-1] = 0, 0
    verts.append(list(zip(xs, ys)))

poly = PolyCollection(verts,facecolors=[cc('r'), cc('g'), cc('b'), cc('y')]*4+[cc('r')])
poly.set_alpha(0.7)
ax.add_collection3d(poly, zs=zs, zdir='y')

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')


plt.title('Density auto power spectrum distribution')
plt.show()

任何幫助將不勝感激,謝謝!

multi_dens_auto_cl_dist 的數據文件

這里還有幾個未知數。 一方面,目前還不清楚你的 dataframe 的結構是什么。 更有問題的是,我們不知道您想如何創建直方圖。 您的代碼為 1001 個數據點創建了 1001 個 bin。 為什么? 當直方圖是特定類型的條形圖時,為什么要嘗試創建多邊形形狀也不清楚。 考慮到這些未知因素,我試圖使腳本盡可能靈活:

from matplotlib import pyplot as plt
import numpy as np
from cycler import cycler
import pandas as pd

inputarr = np.loadtxt("data.txt")
df = pd.DataFrame(inputarr.reshape(1001, 33))
#determine the number of columns
ncol = df.shape[1]

fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(projection="3d")

#since you have so many columns, it is difficult to give them all unique colors
#but we can define through which colors we cycle
#you could also create a range of colors along a color map and give each histogram 
#its unique color, which would then be similar to neighbouring colors
color_cycler = (cycler(color=["tab:orange", "yellow", "red", "blue", "green"]))
ax.set_prop_cycle(color_cycler)

#define the yticks, i.e., the column numbers
yticks = np.arange(ncol)

#just to demonstrate that bins don't have to be evenly spaced, we define normalized bins 
xbinnorm = [0, 0.1, 0.2, 0.3, 0.5, 1]
#we adapt the normalized bins to the minimum and maximum of the entire dataframe
xbins = [df.min().min() + i * (df.max().max()-df.min().min()) for i in xbinnorm]

#calculate now the histogram and plot it for each column
for ytick in yticks:
    
    #extract the current column from your df by its number
    col =  df.iloc[:, ytick]
    
    #determine the histogram values, here you have to adapt it to your needs
    histvals, edges = np.histogram(col, bins=xbins)
    
    #calculate the center and width of each bar
    #obviously not necessary to do this for each column if you always have the same bins 
    #but if you choose for np.histogram other parameters, the bins may not be the same for each histogram
    xcenter = np.convolve(edges, np.ones(2), "valid")/2
    xwidth = np.diff(edges)

    #plot the histogram as a bar for each bin
    ax.bar(left=xcenter, height=histvals, width=xwidth, zs=ytick, zdir="y", alpha=0.666)

ax.set_xlabel("bin")
ax.set_ylabel("column")
ax.set_zlabel("value")

#label every other column number
ax.set_yticks(yticks[::2])
#label bin edges, obviously only possible if all have the same bins
ax.set_xticks(xbins)

plt.show()

樣品 output:

在此處輸入圖像描述

更新
鑒於我們實際上在您的數據中看到了發展,連續的顏色圖可能會提供更多信息(並減少眼科緊急情況)。 實現這一目標不需要太多改變。

from matplotlib import pyplot as plt
import numpy as np
import pandas as pd

inputarr = np.loadtxt("data.txt")
df = pd.DataFrame(inputarr.reshape(1001, 33))
#determine the number of columns
ncol = df.shape[1]

fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(projection="3d")

#define the colormap 
my_cmap = plt.cm.inferno

#define the yticks, i.e., the column numbers
yticks = np.arange(ncol)

#just to demonstrate that bins don't have to be evenly spaced, we define normalized bins 
xbinnorm = [0, 0.1, 0.3, 0.5, 0.8, 1]
#we adapt the normalized bins to the minimum and maximum of the entire dataframe
xbins = [df.min().min() + i * (df.max().max()-df.min().min()) for i in xbinnorm]

#calculate now the histogram and plot it for each column
for i, ytick in enumerate(yticks):

    #extract the current column from your df by its number
    col =  df.iloc[:, ytick]

    #determine the histogram values, here you have to adapt it to your needs
    histvals, edges = np.histogram(col, bins=xbins)

    #calculate the center and width of each bar
    #obviously not necessary to do this for each column if you always have the same bins 
    #but if you choose for np.histogram other parameters, the bins may not be the same for each histogram
    xcenter = np.convolve(edges, np.ones(2), "valid")/2
    xwidth = np.diff(edges)

    #plot the histogram as a bar for each bin
    #now with continuous color mapping and edgecolor, so we can better see all bars
    ax.bar(left=xcenter, height=histvals, width=xwidth, zs=ytick, zdir="y", color=my_cmap(1-i/ncol), alpha=0.666, edgecolor="grey")

ax.set_xlabel("bin")
ax.set_ylabel("column")
ax.set_zlabel("value")

#label every other column number
ax.set_yticks(yticks[::2])
#label bin edges, obviously only possible if all have the same bins
ax.set_xticks(xbins)

plt.show()

樣品 output(具有不同的 bin): 在此處輸入圖像描述

通過刪除與xbins相關的所有內容,此版本還可以輕松適應np.histogram中的bins="auto"選項。 樣品 output 與對面站點的視圖:

在此處輸入圖像描述

更新2

鑒於您的數據結構,您很可能更喜歡均勻間隔的 bin。 在這種情況下,我們不必單獨計算每個切片的條形 position。

from matplotlib import pyplot as plt
import numpy as np
import pandas as pd

inputarr = np.loadtxt("data.txt")
df = pd.DataFrame(inputarr.reshape(1001, 33))
#determine the number of columns
ncol = df.shape[1]

fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(projection="3d")

#define the colormap 
my_cmap = plt.cm.inferno

#define the yticks, i.e., the column numbers
yticks = np.arange(ncol)

#we create evenly spaced bins between the minimum and maximum of the entire dataframe
xbins = np.linspace(df.min().min(), df.max().max(), 100)
#and calculate the center and widths of the bars
xcenter = np.convolve(xbins, np.ones(2), "valid")/2
xwidth = np.diff(xbins)

#calculate now the histogram and plot it for each column
for i, ytick in enumerate(yticks):

    #extract the current column from your df by its number
    col =  df.iloc[:, ytick]

    #determine the histogram values, here you have to adapt it to your needs
    histvals, _ = np.histogram(col, bins=xbins)

    #plot the histogram as a bar for each bin
    #now with continuous color mapping and edgecolor, but thinner lines, so we can better see all bars
    ax.bar(left=xcenter, height=histvals, width=xwidth, zs=ytick, zdir="y", color=my_cmap(i/ncol), alpha=0.666, edgecolor="grey", linewidth=0.3)

ax.set_xlabel("bin")
ax.set_ylabel("column")
ax.set_zlabel("value")

#label every other column number
ax.set_yticks(yticks[::2])
ax.set_zlim3d(0,60)
plt.show()

示例 output(從對面站點查看,第一個直方圖由於與其他直方圖相比值過多而被截斷):

![![在此處輸入圖像描述

免責聲明:滾動平均值計算改編自這個 SO answer

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM