如何将多文件数据合并至单个直方图?Python技术求助
问题背景
当前代码会为每个文件夹下的.ptu文件单独绘制直方图,需求是将所有文件的markerdistance数据合并到同一个直方图中,以便观测整体测量值的离散程度。尝试用seaborn实现时因变量调用错误失败。
原实现代码:
# import libaries import matplotlib.pyplot as plt import matplotlib.image as mpimg import numpy as np import itertools import pandas as pd import scipy.interpolate as interp import ptu_reader_JHU as ptu import csv from scipy.optimize import curve_fit from glob import glob # read all .ptu files in folder files = glob("P:/schlaefke/WRS_Test/New_Data/Multirange_Grid_smallest_Area4/*.ptu") for file in files: # create Array with the timestamps of all markers header, markertime = ptu.ptu_markertime(file) # create array with the distances of the markers markertimeshift=np.empty_like(markertime) markertimeshift[:1]=0 markertimeshift[1:]=markertime[:-1] markerdistance=np.subtract(markertime, markertimeshift) # convert markerdistance into seconds markerdistance = markerdistance*header['MeasDesc_GlobalResolution'] # remove the first marker (sometimes its very fast) markerdist_removed=markerdistance[1:] # create arrays with long and short distances markerdist_group1=markerdist_removed[::2] markerdist_group2=markerdist_removed[1::2] # calculate variance of the line length if max(markerdist_group1)>max(markerdist_group2): average = np.average(markerdist_group1) variance = np.var(markerdist_group1) relvariance = variance/average outlier = max((average-min(markerdist_group1), max(markerdist_group1)-average)) reloutlier = outlier/average else: average = np.average(markerdist_group2) variance = np.var(markerdist_group2) relvariance = variance/average outlier = max((average-min(markerdist_group2), max(markerdist_group2)-average)) reloutlier = outlier/average # find average of long distance average_line=max((np.average(markerdist_group1), np.average(markerdist_group2))) # determine the number of bins. its 10% of the larger distance (10% of the maximum duration of one line) binwidth = average_line/10 binnr = np.floor((max(markerdistance)-min(markerdistance))/binwidth) # create and save plots for i in files: plt.hist(markerdistance, bins=int(binnr)) plt.xlabel('Time of markers (s)') plt.ylabel('Number of markers') plt.show() # export data in csv file with open("P:\\schlaefke\\WRS_Test\\PTU_Data.csv", "a", newline = "") as f: writer = csv.writer(f) writer.writerow([variance, relvariance, outlier, reloutlier])
尝试的seaborn代码(存在错误):
import seaborn as sns data_histogramm = pd.DataFrame(markerdistance, bins=int(binnr)) sns.histplot(data_histogramm, x="Time of markers (s)", y= "Number of markers")
解决方案
核心思路
要实现合并直方图,关键是先收集所有文件的目标数据,再统一计算bins参数并绘制,而非在循环中逐个绘制独立图。
修正后的完整代码
import matplotlib.pyplot as plt import numpy as np import pandas as pd import ptu_reader_JHU as ptu import csv from glob import glob import seaborn as sns # 初始化容器,收集所有文件的标记间隔数据和统计结果 all_markerdistances = [] all_stats = [] # 读取文件夹下所有.ptu文件 files = glob("P:/schlaefke/WRS_Test/New_Data/Multirange_Grid_smallest_Area4/*.ptu") for file in files: # 读取标记时间戳 header, markertime = ptu.ptu_markertime(file) # 计算标记间隔并转换为秒 markertimeshift = np.empty_like(markertime) markertimeshift[:1] = 0 markertimeshift[1:] = markertime[:-1] markerdistance = np.subtract(markertime, markertimeshift) * header['MeasDesc_GlobalResolution'] # 移除第一个标记,加入全局数据列表 markerdist_removed = markerdistance[1:] all_markerdistances.extend(markerdist_removed) # 计算单文件统计量 markerdist_group1 = markerdist_removed[::2] markerdist_group2 = markerdist_removed[1::2] if max(markerdist_group1) > max(markerdist_group2): average = np.average(markerdist_group1) variance = np.var(markerdist_group1) relvariance = variance / average outlier = max((average - min(markerdist_group1), max(markerdist_group1) - average)) reloutlier = outlier / average else: average = np.average(markerdist_group2) variance = np.var(markerdist_group2) relvariance = variance / average outlier = max((average - min(markerdist_group2), max(markerdist_group2) - average)) reloutlier = outlier / average all_stats.append([variance, relvariance, outlier, reloutlier]) # 基于全局数据统一计算bin参数 all_data = np.array(all_markerdistances) average_line = max(np.average(all_data[::2]), np.average(all_data[1::2])) binwidth = average_line / 10 binnr = int(np.floor((max(all_data) - min(all_data)) / binwidth)) # 方式1:用matplotlib绘制合并直方图 plt.figure(figsize=(10,6)) plt.hist(all_markerdistances, bins=binnr, edgecolor='black') plt.xlabel('Time of markers (s)') plt.ylabel('Number of markers') plt.title('Combined Histogram of Marker Times') plt.show() # 方式2:用seaborn绘制合并直方图(修正变量调用错误) df = pd.DataFrame({'Time of markers (s)': all_markerdistances}) plt.figure(figsize=(10,6)) sns.histplot(data=df, x='Time of markers (s)', bins=binnr, edgecolor='black') plt.ylabel('Number of markers') plt.title('Combined Histogram of Marker Times (Seaborn)') plt.show() # 批量导出统计数据到CSV with open("P:\\schlaefke\\WRS_Test\\PTU_Data.csv", "w", newline="") as f: writer = csv.writer(f) writer.writerow(['Variance', 'Relative Variance', 'Outlier', 'Relative Outlier']) writer.writerows(all_stats)
关键修正点
- 移除原代码中嵌套的
for i in files循环,避免重复绘制同一文件的直方图 - 新增
all_markerdistances列表收集所有文件的数据,实现合并展示 - 统一基于全局数据计算bins,保证直方图的区间一致性
- 修正seaborn代码错误:原代码错误将
bins传入DataFrame构造,改为先构造带列名的DataFrame再传入绘图函数 - 改用
writerows批量写入统计数据,避免重复打开文件
内容的提问来源于stack exchange,提问作者Lavy
相关产品推荐
相关产品推荐

