You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将多文件数据合并至单个直方图?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)

关键修正点

  1. 移除原代码中嵌套的for i in files循环,避免重复绘制同一文件的直方图
  2. 新增all_markerdistances列表收集所有文件的数据,实现合并展示
  3. 统一基于全局数据计算bins,保证直方图的区间一致性
  4. 修正seaborn代码错误:原代码错误将bins传入DataFrame构造,改为先构造带列名的DataFrame再传入绘图函数
  5. 改用writerows批量写入统计数据,避免重复打开文件

内容的提问来源于stack exchange,提问作者Lavy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:39:56