如何用Python从双列文本数据中筛选4个极端局部最小值点
筛选极端局部最小值点的解决方案
我有包含x、y两列数据的文本文件,已知数据中存在4个极端局部最小值点,但使用当前代码获取到了全部23个局部最小值,无法筛选出目标的4个点。需要标记这4个点并保存为文本文件。
当前代码:
import numpy as np import glob import pandas as pd from scipy.signal import argrelextrema import matplotlib.pyplot as plt Path = "input/*.txt" input_files = glob.glob(Path) for file_name in input_files: df = pd.read_csv(file_name, header=None, delimiter="\t") x = df[0] y = df[1] minima_indices = argrelextrema(np.array(y), np.less)[0] minima_x = x[minima_indices] minima_y = y[minima_indices] plt.plot(x,y) plt.plot(minima_x,minima_y, "x",markersize = 5)
问题原因
argrelextrema默认仅比较相邻数据点,会把曲线小波动产生的局部极小值全部识别出来,而你需要的是在更大范围内y值显著更小的极端点。
解决方案
提供两种实用方法,可根据你的数据分布选择:
方法1:按y值直接筛选前4个最小点
直接对所有局部最小值按y值升序排序,取前4个,适用于目标点y值明显小于其他局部极小值的场景:
import numpy as np import glob import pandas as pd from scipy.signal import argrelextrema import matplotlib.pyplot as plt Path = "input/*.txt" input_files = glob.glob(Path) for file_name in input_files: df = pd.read_csv(file_name, header=None, delimiter="\t") x = df[0] y = df[1] # 获取所有局部最小值 minima_indices = argrelextrema(np.array(y), np.less)[0] minima_df = pd.DataFrame({'x': x[minima_indices], 'y': y[minima_indices]}) # 按y值从小到大排序,取前4个极端最小值 extreme_minima = minima_df.sort_values(by='y').head(4) # 保存结果到文本文件(命名为原文件名前缀+extreme_minima) output_file = f"extreme_minima_{file_name.split('/')[-1]}" extreme_minima.to_csv(output_file, sep='\t', index=False, header=False) # 绘图标记目标点 plt.plot(x, y, label='原始曲线') plt.plot(extreme_minima['x'], extreme_minima['y'], "rx", markersize=8, label='极端局部最小值') plt.legend() plt.show()
方法2:按邻域范围筛选(避免近距离冗余点)
如果目标点分布在不同的x轴区间,可设定邻域窗口,每个窗口内仅保留y值最小的点,确保最终得到4个分散的极端点:
import numpy as np import glob import pandas as pd from scipy.signal import argrelextrema import matplotlib.pyplot as plt Path = "input/*.txt" input_files = glob.glob(Path) # 根据你的x轴数据范围调整窗口大小,确保每个目标点单独落在一个窗口内 window_size = 20 # 示例值,需根据实际数据修改 for file_name in input_files: df = pd.read_csv(file_name, header=None, delimiter="\t") x = df[0] y = df[1] minima_indices = argrelextrema(np.array(y), np.less)[0] minima_df = pd.DataFrame({'x': x[minima_indices], 'y': y[minima_indices]}) # 按x值排序,划分邻域筛选 minima_sorted = minima_df.sort_values(by='x').reset_index(drop=True) extreme_minima = [] current_window_start = minima_sorted['x'].iloc[0] while not minima_sorted.empty: # 提取当前窗口内的所有点 window_points = minima_sorted[minima_sorted['x'] <= current_window_start + window_size] if not window_points.empty: # 保留窗口内y值最小的点 min_point = window_points.loc[window_points['y'].idxmin()] extreme_minima.append(min_point) # 移除当前窗口内的点,处理下一个窗口 minima_sorted = minima_sorted[minima_sorted['x'] > current_window_start + window_size] if not minima_sorted.empty: current_window_start = minima_sorted['x'].iloc[0] else: break extreme_minima = pd.DataFrame(extreme_minima) # 保存结果 output_file = f"extreme_minima_{file_name.split('/')[-1]}" extreme_minima[['x', 'y']].to_csv(output_file, sep='\t', index=False, header=False) # 绘图展示 plt.plot(x, y, label='原始曲线') plt.plot(extreme_minima['x'], extreme_minima['y'], "rx", markersize=8, label='极端局部最小值') plt.legend() plt.show()
内容的提问来源于stack exchange,提问作者Hisham
相关产品推荐
相关产品推荐

