我有一个时间序列数据集,需要进行插值,以便任何超过 3 分钟的间隙都保留为空值。
我面临的问题是,即使有接近该时间段的数据,Polars 上采样也会导致大量空值。这是数据框的片段。
utc gnd_p gnd_t app_sza azimuth xh2o xair xco2 xch4 xco xch4_s5p
0 2022-06-04 04:49:31 955.081699 293.84 77.009159 -109.292040 4118.807354 0.996515 421.510185 1.878339 0.0 0.0
1 2022-06-04 04:49:46 955.081655 293.84 76.971435 -109.250593 4119.081639 0.996508 421.543444 1.878761 0.0 0.0
这是相同操作的 Pandas 代码
output = sensor_dataframe.sort_values(by=['utc']) # sort according to time
output['utc'] = pd.to_datetime(output['utc'])
# Apply smoothing function for all data columns.
for column in output.columns[1::]:
output[column] = scipy.signal.savgol_filter(pd.to_numeric(output[column]), 31, 3)
print(output)
output = output.set_index('utc')
output.index = pd.to_datetime(output.index)
output = output.resample(sampling_rate).mean()
sampling_delta = pd.to_timedelta(sampling_rate)
# The interpolating limit is dependant on the sampling rate.
interpolating_limit = int(MAX_DELTA_FOR_INTERPOLATION / sampling_delta)
if interpolating_limit != 0:
output.interpolate(
limit=interpolating_limit,
inplace=True,
limit_direction='both',
limit_area='inside',
)
这是 10 秒采样率的输出。
gnd_p gnd_t app_sza azimuth xh2o xair xco2 xch4 xco xch4_s5p
utc
2022-06-04 04:49:30 955.081699 293.84 77.009159 -109.292040 4118.807354 0.996515 421.510185 1.878339 0.0 0.0
2022-06-04 04:49:40 955.081655 293.84 76.971435 -109.250593 4119.081639 0.996508 421.543444 1.878761 0.0 0.0
这是对 Polars 版本的相同尝试。
df = pl.from_pandas(sensor_dataframe)
q = df.lazy().with_column(pl.col('utc').str.strptime(pl.Datetime, fmt='%F %T').cast(pl.Datetime)).select([pl.col('utc'),
pl.exclude('utc').map(lambda x: savgol_filter(x.to_numpy(), 31, 3)).explode()])
df = q.collect()
df = df.upsample(time_column="utc", every="10s")
这是上述截图的输出
│ 2022-06-04 04:49:31 ┆ 955.081699 ┆ 293.84 ┆ 77.009159 ┆ ... ┆ 421.510185 ┆ 1.878339 ┆ 0.0 ┆ 0.0 │
│ 2022-06-04 04:49:41 ┆ null ┆ null ┆ null ┆ ... ┆ null ┆ null ┆ null ┆ null │
│ 2022-06-04 04:49:51 ┆ null ┆ null ┆ null ┆ ... ┆ null ┆ null ┆ null ┆ null │
Polars 只是吐出一个带有大量 null 的 df 。我必须进行插值来填充值,但这意味着我要对整个数据集进行插值。不幸的是,Polars 没有在 interpolate() 上提供参数或参数,这导致所有系列都被插值,这不是所需的操作。
我认为解决方案应该与口罩有关。有人有使用极坐标和插值的经验吗?
可重现代码:https://pastebin.com/gQ1WU4zp 示例 csv 数据:https://0bin.net/paste/3fX2AOM2#uQmEv2KvBK5Xk-2vuWxx2z0QgXlttdnaa78eFt8ra62
我不会下载您的整个数据集,所以让我们以此为例:
np.random.seed(0)
df = pl.DataFrame(
{
"time": pl.datetime_range(
datetime(2023, 2, 1),
datetime(2023, 2, 2),
interval="1m",
eager=True),
'data':list(np.random.choice([None, 1,2,3,4], size=1441))
}).filter(~pl.col('data').is_null())
upsample,根据定义,不会插值,它(正如您所发现的)只是插入一堆空值来匹配您想要的周期。
如果您只想在预上采样间隙为 3m 或更小时进行插值,请在上采样之前创建一个辅助列。
使用
when
then
查看辅助列来插值或不插值。
df \
.with_columns(
(pl.col('time')-pl.col('time').shift()<pl.duration(minutes=3)).alias('small_gap')) \
.upsample(time_column="time", every="10s") \
.with_columns(pl.col('small_gap').backward_fill()) \
.with_columns(
pl.when(pl.col('small_gap')) \
.then(pl.exclude('small_gap').interpolate()) \
.otherwise(pl.exclude('small_gap'))) \
.drop('small_gap')