python - 如何从 30 个 csv 文件制作直方图以绘制直方图,然后使用高斯函数和标准差绘制直方图?
问题描述
我想从 30 个 csv 文件中制作一个直方图,然后拟合一个高斯函数来查看我的数据是否是最优的。之后,我需要找到这些峰的平均值和标准差。文件数据太大,我不知道我是否提取了单个列并将它们的值范围正确地组织到了 bin 的数量中。
我知道这有点长而且问题太多,请尽可能多地回答,非常感谢!
到目前为止我已经完成了以下(实际上并不多,因为我是数据可视化的初学者。)首先,我导入包,savgol_filter
使bin透明,看起来更好。
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy.signal import savgol_filter
然后我转换尺寸并设置限制。
def cm2inch(value):
return value/2.54
width = 9
height = 6.75
sliceMin, sliceMax = 300, 1002
接下来,我通过迭代 30 次加载所有数据 jupyter notebook,其中我设置了两个数组“times”和“voltages”来存储值。
times, voltages = [], []
for i in range(30):
time, ch1 = np.loadtxt(f"{i+1}.txt", delimiter=',', skiprows=5,unpack=True)
times.append(time)
voltages.append(ch1)
t = (np.array(times[0]) * 1e5)[sliceMin:sliceMax]
voltages = (np.array(voltages))[:, sliceMin:sliceMax]
1. 我想我应该需要一个 hist 函数来绘制图表。虽然我有情节,但我不确定它是否是生成直方图的正确方法。
hist, bin_edges = np.histogram(voltages, bins=500, density=True)
hist = savgol_filter(hist, 51, 3)
bin_centres = (bin_edges[:-1] + bin_edges[1:])/2
到目前为止,我已经达到了。第三个峰值的幅度太低,这不是我所期望的。但是,如果我的期望是错误的,请纠正我。
labels = "hist"
if showGraph:
plt.title("Datapoints Distribution over Voltage [mV]", )
plt.xlabel("Voltage [mV]")
plt.ylabel("Data Points")
plt.plot(hist, label=labels)
plt.show()
2.(已编辑)我不知道为什么我的标签无法显示,您能纠正我吗?
3.(已编辑)此外,我想通过对直方图使用高斯函数来制作拟合曲线。但是有三个峰值,那么我应该如何使函数适合它们呢?
def gauss(x, *p):
A, mu, sigma = p
return A*np.exp(-(x-mu)**2/(2.*sigma**2))
4.(已编辑)我意识到我还没有提到平均值。我想如果我可以找到峰值的最大值,那么我可以找到特定峰值的平均值。我需要先拟合高斯才能找到峰值,还是可以找到直线?是否要找到局部最大值以便我找到它?如果是,我该如何进行?
5.(已编辑)我知道如何从单个列表中找到标准差,如果我想做类似的逻辑,如何实现代码?
sample = [1,2,3,4,5,5,5,5,10]
standard_deviation = np.std(sample, ddof=1)
print(standard_deviation)
对建议的反馈:我尝试实现高斯拟合,以下是我导入的包。
from sklearn.mixture import GaussianMixture
import numpy as np
import matplotlib.pyplot as plt
这是高斯函数,我将我的 30 个数据集电压作为高斯混合拟合的参数,它打印了我们关于mu
和的许多值variance
。
gmm = GaussianMixture(n_components=1)
gmm.fit(voltages)
print(gmm.means_, gmm.covariances_)
mu = gmm.means_[0][0]
variance = gmm.covariances_[0][0][0]
print(mu, variance)
我一一处理代码。第二行有错误:
fig, ax = plt.subplots(figsize=(6,6))
Xs = np.arange(min(voltages), max(voltages), 0.05)
具有多个元素的数组的真值是不明确的。使用 a.any() 或 a.all()
我从网上搜索到,用这个表示只有一个值,比如如果有[T,T,F,F,T],你可以有4种可能性。
我将代码编辑为:
Xs = np.arange(min(np.all(voltages)), max(np.all(voltages)), 0.05)
这给了我这个:
'numpy.bool_' 对象不可迭代
我知道它不是一个布尔对象。在这个阶段,我不知道如何进行高斯曲线拟合。任何人都可以为我提供另一种方法吗?
解决方案
- 要绘制直方图,最普通的
matplotlib
函数hist
是我的首选。基本上,如果我有一个 列表samples
,那么我可以通过以下方式用 bin 绘制它们的直方图100
:
import matplotlib.pyplot as plt
plt.hist(samples, bins=100)
plt.show()
- 如果您想将正态分布拟合到您的数据中,最好的模型是高斯混合模型,您可以通过scikit-learn 的 GMM 页面找到更多信息。也就是说,这是我用来将奇异高斯分布拟合到数据集的代码。如果我想拟合
k
正态分布,我需要使用n_components=k
. 我还包括了结果图:
from sklearn.mixture import GaussianMixture
import numpy as np
import matplotlib.pyplot as plt
data = np.random.uniform(-1,1, size=(800,1))
data += np.random.uniform(-1,1, size=(800,1))
gmm = GaussianMixture(n_components=1)
gmm.fit(data)
print(gmm.means_, gmm.covariances_)
mu = gmm.means_[0][0]
variance = gmm.covariances_[0][0][0]
print(mu, variance)
fig, ax = plt.subplots(figsize=(6,6))
Xs = np.arange(min(data), max(data), 0.05)
ys = 1.0/np.sqrt(2*np.pi*variance) * np.exp(-0.5/variance * (Xs + mu)**2)
ax.hist(data, bins=100, label='data')
px = ax.twinx()
px.plot(Xs, ys, c='r', linestyle='dotted', label='fit')
ax.legend()
px.legend(loc='upper left')
plt.show()
至于问题 3,我不确定您要捕获哪个轴的标准差。如果您想获得列的标准差,可以使用np.std(data, axis=1)
, 和axis=0
用于逐行标准差。
推荐阅读
- linux - Linux:如何压缩大约 3TB 大小的文件夹
- php - 通过使用 2 个关键字搜索从字符串中提取一部分
- laravel - Shopify Public APP,卸载前删除应用代码
- python - 这个代码段是什么意思?
- reactjs - 如何在本机反应中按字母顺序加载联系人?
- rust - 试图在 Rust 中返回一个字符串切片数组,但我收到错误,我无法返回引用临时值的值
- python - Python烧瓶应用程序容器图像无法解析内部模块
- docker - 在 Docker 容器中运行时无法在本地保存 Jupyter Notebook
- python - Multiindex Dataframe,如何获取索引值?
- kubernetes - Kubernetes pod 亲和性 - 在不同节点上调度 pod