如何用正弦/线性函数填充Pandas列?潮汐极值列补全需求
用自定义函数填充潮汐水位缺失值的实现方案
嘿,这个需求我之前处理过类似的场景,用Pandas就能轻松搞定!核心思路是先定位你的潮汐峰值(非缺失值的行),把相邻峰值之间的缺失区间分组,再用你想要的线性/正弦函数填充每个区间。下面给你一步步拆解:
1. 标记并提取峰值位置
首先得把所有的潮汐峰值(非缺失的水位值)找出来,给它们做个标记,方便后续分组:
import pandas as pd import numpy as np # 假设你的DataFrame叫df,水位列是water_level df['is_peak'] = df['water_level'].notna() # 提取所有峰值的索引和对应水位值,方便后续参考 peaks = df[df['is_peak']][['water_level']].reset_index()
2. 为缺失区间分配分组ID
接下来要给每一段缺失值区间分配一个唯一的分组ID,这样我们就知道每个缺失段属于哪两个峰值之间:
# 每遇到一个峰值,分组ID就加1,这样相邻峰值之间的缺失值会被分到同一个组里 df['group_id'] = df['is_peak'].cumsum() # 如果你DataFrame开头有缺失值(第一个行就是空的),可以选择丢弃这段或者用第一个峰值填充,这里先处理中间的有效区间 df = df[df['group_id'] != 0]
3. 自定义填充函数(线性/正弦示例)
现在就可以针对每个分组,用你想要的函数填充缺失值了,这里给你两个最常用的实现:
线性插值填充(简单直接)
如果想要最基础的直线填充,用线性插值就行:
def linear_fill(group): # 获取当前分组的起始和结束峰值 start_val = group['water_level'].dropna().iloc[0] end_val = group['water_level'].dropna().iloc[-1] # 生成从start到end的线性序列,刚好填满整个分组 group['water_level'] = np.linspace(start_val, end_val, len(group)) return group # 对每个分组应用线性填充 df_filled_linear = df.groupby('group_id').apply(linear_fill)
正弦函数填充(贴合潮汐特性)
潮汐变化更接近正弦曲线,用正弦函数填充会更符合实际潮汐的波动规律:
def sine_fill(group): start_val = group['water_level'].dropna().iloc[0] end_val = group['water_level'].dropna().iloc[-1] # 计算两个峰值的差值和中间值 peak_diff = end_val - start_val mid_level = (start_val + end_val) / 2 # 生成0到π的正弦曲线(刚好覆盖从一个峰值到另一个峰值的半周期) x = np.linspace(0, np.pi, len(group)) # 调整正弦曲线的幅度和偏移,让它刚好连接两个峰值 group['water_level'] = mid_level + (peak_diff / 2) * np.cos(x) return group # 应用正弦填充 df_filled_sine = df.groupby('group_id').apply(sine_fill)
4. 处理特殊情况(可选)
- 如果DataFrame开头有缺失值:可以用
df['water_level'].bfill()把第一个峰值向前填充,或者直接删除这段数据 - 如果DataFrame结尾有缺失值:用
df['water_level'].ffill()把最后一个峰值向后填充,或者删除 - 如果有连续的峰值(两个非缺失值相邻):分组后会自动跳过,不需要填充
5. 验证填充效果
最后可以画个图看看填充的结果对不对:
import matplotlib.pyplot as plt plt.figure(figsize=(12, 6)) plt.plot(df_filled_sine.index, df_filled_sine['water_level'], label='正弦填充结果') plt.scatter(peaks['index'], peaks['water_level'], color='red', s=50, label='原始潮汐峰值') plt.legend() plt.title('潮汐水位缺失值填充效果') plt.show()
你还可以根据实际潮汐的周期调整正弦函数的参数,比如把np.pi改成2*np.pi来模拟完整周期,或者调整幅度让填充更贴合你的数据~
内容的提问来源于stack exchange,提问作者Borja Fernández Antelo
相关产品推荐
相关产品推荐

