如何在DataFrame指定行集上批量应用自定义公式?
批量处理DataFrame分段数据的线性拟合方案
看起来你已经完成了最关键的一步——定位出了分隔各个<PROFIEL>段的行位置(indicatie列表),现在只需要把这些位置转换成可批量处理的数据区间,就能自动对每个区间的x和y应用你的线性拟合函数了。我来给你整理一套可行的解决方案:
核心思路
你的indicatie列表里的数值是那些非<METING>的行索引(也就是每个<PROFIEL>的开头和结尾标记),其中连续的数值对(比如12和13、26和27)就是一个<PROFIEL>的首尾边界。我们需要把这些边界转换成中间有效数据段的索引范围,然后遍历每个范围自动调用rechtzetten函数。
完整实现代码
import pandas as pd import numpy as np # 读取数据源 df = pd.read_csv('Dalfsen.csv') # 优化你的线性拟合函数:返回拟合结果和参数,方便后续分析 def rechtzetten(x, y): n = len(x) # 避免除数为0的情况(比如x全相同) denominator = n * np.sum(x**2) - np.sum(x)**2 if denominator == 0: print("警告:x值全部相同,无法拟合直线") return None, None, None a = (n * np.sum(x*y) - np.sum(x)*np.sum(y)) / denominator b = (np.sum(y) - a * np.sum(x)) / n y_fit = x * a + b print(f"拟合参数 a: {a:.4f}, b: {b:.4f}") return y_fit, a, b # 定位非<METING>的行(即分隔行) METING = df.ID.str.contains("<METING>") indicatie = np.where(METING == False)[0] # 生成需要处理的有效数据区间 intervals = [] i = 0 total_separators = len(indicatie) while i < total_separators - 1: current_sep = indicatie[i] next_sep = indicatie[i+1] # 如果两个分隔行是连续的,说明是一个<PROFIEL>的首尾,跳过这对 if next_sep == current_sep + 1: i += 2 else: # 有效数据段是从当前分隔行的下一行,到下一个分隔行的前一行 start_idx = current_sep + 1 end_idx = next_sep - 1 intervals.append((start_idx, end_idx)) i += 1 # 遍历所有区间,批量应用拟合函数 fit_results = [] for seg_num, (start, end) in enumerate(intervals, 1): print(f"\n=== 处理第 {seg_num} 个数据段(索引范围: [{start}, {end}]) ===") # 提取当前段的x和y值 x_data = df.loc[start:end, 'x'].values y_data = df.loc[start:end, 'y'].values # 确保数据段有足够的点(至少2个点才能拟合直线) if len(x_data) < 2: print("数据段点数不足,跳过拟合") continue # 调用拟合函数 y_fitted, a_param, b_param = rechtzetten(x_data, y_data) if y_fitted is not None: fit_results.append({ "segment_number": seg_num, "start_index": start, "end_index": end, "slope_a": a_param, "intercept_b": b_param, "fitted_y": y_fitted }) # 可选:把结果转换成DataFrame,方便查看和导出 results_df = pd.DataFrame(fit_results) print("\n=== 所有拟合结果汇总 ===") print(results_df[["segment_number", "start_index", "end_index", "slope_a", "intercept_b"]])
代码细节说明
- 区间生成逻辑:通过循环遍历
indicatie列表,跳过连续的分隔行对(这些是<PROFIEL>的首尾标记),自动提取中间的有效数据段索引范围,完全不需要手动写[1:11]这类区间。 - 函数优化:增加了除数为0的异常处理(比如x值全部相同的情况),同时返回拟合结果和参数,方便后续保存或进一步分析。
- 边界检查:添加了数据段点数判断,避免因为点数不足导致的计算错误。
- 结果保存:把每个段的拟合结果存储在列表中,最后可以转换成DataFrame统一查看,也可以导出为CSV文件(比如
results_df.to_csv("fit_results.csv", index=False))。
示例运行效果
假设某个数据段有足够的有效数据,会输出类似这样的内容:
=== 处理第 1 个数据段(索引范围: [1, 11]) === 拟合参数 a: 0.8765, b: 2.3456 === 处理第 2 个数据段(索引范围: [14, 25]) === 拟合参数 a: -1.2345, b: 6.7890 === 所有拟合结果汇总 === segment_number start_index end_index slope_a intercept_b 0 1 1 11 0.8765 2.3456 1 2 14 25 -1.2345 6.7890
这样就能完全替代你手动编写几百次重复代码的工作啦!
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

