在 python 中将散点图转换为直方图

Turning a scatter plot into a histogram in python

我需要根据另一个文件中的一些数据绘制直方图。

目前我有绘制散点图并适合高斯分布的代码。

x 值是它正在读入的数据文件中相应行上的数字(在其他信息的前 12 行之后,即第 13 行是第一个事件),y 值是行数乘以一个值。

然后绘制并拟合散点图,但我需要能够将其绘制为直方图,并能够更改 bin 宽度/数量(即,将 bin 1、2、3 和 4 加在一起得到 1 /4 的垃圾箱总体上是事件数量的 4 倍 - 所以我想将数据中的多行加在一起),这就是我被困的地方。

我该如何将其制作成直方图并调整宽度/数字?

下面的代码,不知道如何让它更漂亮。让我知道是否可以让它更容易阅读。

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from numpy import exp, loadtxt, pi, sqrt, random, linspace
from lmfit import Model
import glob, os

## Define gaussian
def gaussian(x, amp, cen, wid):
    """1-d gaussian: gaussian(x, amp, cen, wid)"""
    return (amp / (sqrt(2*pi) * wid)) * exp(-(x-cen)**2 / (2*wid**2))

## Define constants
stderrThreshold = 10
minimumAmplitude = 0.1
approxcen = 780
MaestroT = 53

## Define paramaters
amps = []; ampserr = []; ts = []
folderToAnalyze = baseFolder + fileToRun + '\'

## Generate the time array

for n in range(0, numfiles):
    
    ## Load text file
    x = np.linspace(0, 8191, 8192) 
    fullprefix = folderToAnalyze + prefix + str(n).zfill(3)
    y = loadtxt(fullprefix + ".Spe", skiprows= 12, max_rows = 8192) 

    ## Make figure
    fig, ax = plt.subplots(figsize=(15,8))
    fig.suptitle('Coincidence Detections', fontsize=20)
    plt.xlabel('Bins', fontsize=14)
    plt.ylabel('Counts', fontsize=14)

    ## Plot data
    ax.plot(x, y, 'bo')
    ax.set_xlim(600,1000)

    ## Fit data to Gaussian
    gmodel = Model(gaussian)
    result = gmodel.fit(y, x=x, amp=8, cen=approxcen, wid=1)

    ## Plot results and save figure
    ax.plot(x, result.best_fit, 'r-', label='best fit')
    ax.legend(loc='best')
    texttoplot = result.fit_report()
    ax.text(0.02, 0.5, texttoplot, transform=ax.transAxes)
    plt.close()
    fig.savefig(fullprefix + ".png", pad_inches='0.5')    

当前输出:散点图,确实显示了预期的分布和数据图(但是它们确实减少了 chi^2,但一次出现一个问题)

预期输出:相同数据的直方图,具有相同的分布和拟合,当每个事件被绘制为一个单独的 bin 时,希望可以将这些 bin 加在一起以减少误差线

错误:N/A

数据:基本上是8192行的标准分布。 1 个文件的完整数据是 here. Also the original .Spe file, the scatter plot and the full version of the code

2020-11-23 回复评论更新:

  • 在这种情况下,scatter plot 是直方图,只是用点代替了条。
  • .Spe 是每个事件的 bin 计数。
  • x = np.linspace(0, 8191, 8192)定义bin,bin宽度为1。
  • 构建条形图而不是散点图
    • ax.bar(x, y) 而不是 ax.plot(x, y, 'bo')
  • 由于已有数据,下图是一个分布很广的直方图。
    • 有从 321 到 1585 的值
    • ax.set_xlim(300, 1800)

  • 此数据的好处是,可以很容易地重新创建基于 x 的原始分布,bin 大小为 1,y 是每个 x 的相应计数.
  • np.repeat可以创建一个包含重复元素的数组
import numpy
import matplotlib.pyplot as plt

# given x and y from the loop
# set the type as int
y = y.astype(int)
x = x.astype(int)

# create the data
data = np.repeat(x, y)

# determine the range of x
x_range = range(min(data), max(data)+1)

# determine the length of x
x_len = len(x_range)

# plot
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(10, 10))

ax1.hist(data, bins=x_len)  # outliers are not plotted
ax2.boxplot(data, vert=False)
plt.show()

  • 鉴于 data,您现在可以执行任何需要的分析。
  • LMFIT Docs
  • Cross Validated 可能是深入研究模型的更好站点
  • 所有误差计算参数均来自模型result。如果您根据 np.histogram 为不同的 bin 宽度计算新的 xy,这可能会影响错误。
    • approxcen = 780 也是 result
    • 的输入
# given x_len determine how many bins for a given bin width
width = 8
bins = int(np.round(x_len / width))

# determine new x and y for the histogram
y, x = np.histogram(data, bins=bins)

# Fit data to Gaussian
gmodel = Model(gaussian)
result = gmodel.fit(y, x=x[:-1], amp=8, cen=approxcen, wid=1)

# result
print(result.fit_report())

[out]:
[[Model]]
    Model(gaussian)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 314
    # data points      = 158
    # variables        = 3
    chi-square         = 397.702574
    reduced chi-square = 2.56582306
    Akaike info crit   = 151.851284
    Bayesian info crit = 161.039069
[[Variables]]
    amp:  1174.80608 +/- 37.1663147 (3.16%) (init = 8)
    cen:  775.535731 +/- 0.46232727 (0.06%) (init = 780)
    wid:  12.6563219 +/- 0.46232727 (3.65%) (init = 1)
[[Correlations]] (unreported correlations are < 0.100)
    C(amp, wid) =  0.577

# plot
plt.figure(figsize=(10, 6))
plt.bar(x[:-1], y)
plt.plot(x[:-1], result.best_fit, 'r-', label='best fit')

plt.figure(figsize=(20, 8))
plt.bar(x[:-1], y)
plt.xlim(700, 850)
plt.plot(x[:-1], result.best_fit, 'r-', label='best fit')
plt.grid()

  • 从下一个代码块可以看出,错误与以下参数有关
    • stderrThreshold = 10
    • minimumAmplitude = 0.1
    • MaestroT = 53
    ## Append to list if error in amplitude and amplitude itself is within reasonable bounds
    if result.params['amp'].stderr < stderrThreshold and result.params['amp'] > minimumAmplitude:
        amps.append(result.params['amp'].value) 
        ampserr.append(result.params['amp'].stderr) 
        ts.append(MaestroT*n)