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

Python 如何使不同长度的不同数据帧长度相等(下采样和上采样),python,pandas,time-series,interpolation,resampling,Python,Pandas,Time Series,Interpolation,Resampling,我有许多数据帧(时间序列),它们的长度在28到179之间。我要把它们做成104码长的。(对104以下的进行上采样,对104以上的进行下采样) 对于上采样,线性方法足以满足我的需要。对于下采样,值的平均值应良好 为了使所有文件都具有相同的长度,我认为需要使所有数据帧在相同的日期开始和结束 我能够使用以下代码行将所有样本缩减到最小数据帧(即28)的大小: df.set_index(pd.date_range(start='1/1/1991' ,periods=len(df), end='1/1/20

我有许多数据帧(时间序列),它们的长度在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
假设平均长度为6,预期输出为:

使用插值将df1上采样到长度6,例如
resamle(规则).interpolate()

使用
重采样(规则).mean()
将df2下采样至长度6

更新:


如果我能将所有文件的采样值提升到179,那也没问题。

我假设问题是,在提升采样的情况下,当您进行重采样时,其他值不会保留。对于示例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
因此,当您执行
插值
而不是
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())

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

这是我使用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

我认为pandas Groupby可能会在这方面有所帮助,但我对python不太熟悉,我不知道如何应用它来解决这个问题。最终我使用了:
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抱歉,我没有遵循,结果与?我看到您更改了日期范围和重采样值,但您的意思是该方法不适用于这些设置?它给出了与中相同的结果,还执行了正确的上采样和下采样。这意味着开始和结束日期的更改实际上对最终结果影响不大。更改的日期更有意义,因为我的文件最长的长度是179。
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