如何使不同长度的不同数据帧长度相等(下采样和上采样)

Posted

技术标签:

【中文标题】如何使不同长度的不同数据帧长度相等(下采样和上采样)【英文标题】:How to make different dataframes of different lengths become equal in length (downsampling and upsampling) 【发布时间】:2019-12-30 20:08:58 【问题描述】:

我有许多长度在 28 到 179 之间的不同长度的数据帧(时间序列)。我需要将它们全部设为 104。(对低于 104 的数据进行上采样,对高于 104 的数据进行下采样)

对于上采样,线性方法足以满足我的需要。对于下采样,值的平均值应该很好。

为了让所有文件的长度相同,我认为我需要让所有数据帧在相同的日期开始和结束。

我能够使用以下代码行将所有数据下采样到最小数据帧的大小(即 28):

df.set_index(pd.date_range(start='1/1/1991' ,periods=len(df), end='1/1/2000'), inplace=True)

resampled=df.resample('120D').mean()

但是,当我将它们输入到我需要它们的模型中时,这不会给我带来很好的结果,因为它会大大缩小较长的文件,从而扭曲数据。

这是我迄今为止尝试过的:

df.set_index(pd.date_range(start='1/1/1991' ,periods=len(df), end='1/1/2000'), inplace=True)

if df.shape[0]>100: resampled=df.resample('D').mean()

elif df.shape[0]<100: resampled=df.astype(float).resample('33D').interpolate(axis=0, method='linear')

else: break

现在,在上面的代码行中,我让文件的长度相同(长度为 100)。下采样部分也可以正常工作。

上采样部分的 interpoaltion 不起作用。它只返回长度为 100 的数据帧每列的第一个值刚刚复制到所有行

我需要将它们全部设为 104(平均尺寸)。这意味着任何长度>104的df都需要下采样,任何长度

例如,请考虑以下两个df:

>>df1

index                                                                 
0       3   -1    0            
1       5   -3    2          
2       9   -5    0 
3      11   -7   -2     

>>df2

index                                                                 
0       3   -1    0            
1       5   -3    2          
2       9   -5    0
3       6   -3   -2
4       4    0   -4
5       8    2   -6
6      10    4   -8
7      12    6   -10

假设平均长度为 6,预期输出为

df1 上采样 使用插值到长度 6 - 例如resamle(rule).interpolate().

并且使用resample(rule).mean() df2 下采样到长度 6。

更新:

如果我可以将所有文件上采样到 179,那也很好。

【问题讨论】:

我认为 pandas Groupby 在这里可能会有所帮助,但我是 python 新手,我不知道如何准确地应用它来解决这个问题。 【参考方案1】:

我认为问题是当您在上采样情况下执行resample 时,不会保留其他值。使用示例 df1,您可以在一列上使用 asfreq 来查看它:

print (df1.set_index(pd.date_range(start='1/1/1991' ,periods=len(df1), end='1/1/2000'))[1]
          .resample('33D').asfreq().isna().sum(0))
#99 rows are nan on the 100 length resampled dataframe

因此,当您执行interpolate 而不是asfreq 时,它实际上只使用第一个值进行插值,这意味着第一个值在所有行中“重复”

要得到你想要的结果,那么在插值之前,即使在上采样的情况下也要使用mean,例如:

print (df1.set_index(pd.date_range(start='1/1/1991' ,periods=len(df1), end='1/1/2000'))[1]
          .resample('33D').mean().interpolate().head())
1991-01-01    3.000000
1991-02-03    3.060606
1991-03-08    3.121212
1991-04-10    3.181818
1991-05-13    3.242424
Freq: 33D, Name: 1, dtype: float64

你会得到你想要的值。

总而言之,我认为在上采样和下采样的情况下,您可以使用相同的命令

resampled = (df.set_index(pd.date_range(start='1/1/1991' ,periods=len(df), end='1/1/2000'))
               .resample('33D').mean().interpolate())

因为interpolate 不会影响下采样情况下的结果。

【讨论】:

最终我使用了:resampled=(df.set_index(pd.date_range(start='1/1/1991' ,periods=len(df), end='30/3/1991')) .resample('20H').mean().interpolate())。确实产生相同的结果(除了这些日期和规则产生的长度是 106)。日期范围似乎更合理。 @R.A 抱歉,我没有关注,结果与?我看到您更改了 date_range 和 resample 值,但您的意思是该方法不适用于这些设置? 它给出的结果与它执行正确的上采样和下采样相同。这意味着开始和结束日期的更改并不会真正影响最终结果。更改的日期更有意义,因为我的文件的最长长度是 179。【参考方案2】:

这是我使用 skimage.transform.resize() 函数的版本:

df1 = pd.DataFrame(
                    'a': [3,5,9,11],
                    'b': [-1,-3,-5,-7],
                    'c': [0,2,0,-2]
                   )
df1

    a   b   c
0   3   -1  0
1   5   -3  2
2   9   -5  0
3   11  -7  -2


import pandas as pd
import numpy as np
from skimage.transform import resize

def df_resample(df1, num=1):
    df2 = pd.DataFrame()
    for key, value in df1.iteritems(): 
        temp = value.to_numpy()/value.abs().max() # normalize
        resampled = resize(temp, (num,1), mode='edge')*value.abs().max() # de-normalize
        df2[key] = resampled.flatten().round(2)
    return df2


df2 = df_resample(df1, 20) # resampling rate is 20
df2

    a   b   c
0   3.0     -1.0    0.0
1   3.0     -1.0    0.0
2   3.0     -1.0    0.0
3   3.4     -1.4    0.4
4   3.8     -1.8    0.8
5   4.2     -2.2    1.2
6   4.6     -2.6    1.6
7   5.0     -3.0    2.0
8   5.8     -3.4    1.6
9   6.6     -3.8    1.2
10  7.4     -4.2    0.8
11  8.2     -4.6    0.4
12  9.0     -5.0    0.0
13  9.4     -5.4    -0.4
14  9.8     -5.8    -0.8
15  10.2    -6.2    -1.2
16  10.6    -6.6    -1.6
17  11.0    -7.0    -2.0
18  11.0    -7.0    -2.0
19  11.0    -7.0    -2.0

【讨论】:

以上是关于如何使不同长度的不同数据帧长度相等(下采样和上采样)的主要内容,如果未能解决你的问题,请参考以下文章

为spark scala中的数据框中的每个组采样不同数量的随机行

下采样 wav 音频文件

语音处理加窗分帧

合并两个 Pandas 数据帧,在一个时间列上重新采样,插值

如何通过 2x2 平均内核对 pandas 数据帧进行下采样

如何禁用Oracle AWR自动采样功能