如何使不同长度的不同数据帧长度相等(下采样和上采样)
How to make different dataframes of different lengths become equal in length (downsampling and upsampling)
我有许多长度在 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 不起作用。它只是 returns 个长度为 100 的数据帧,每列的第一个值刚刚复制到所有行。
我需要的是将它们全部设为 104(平均尺寸)。这意味着任何长度>104 的 df 都需要下采样,任何长度<104 的 df 都需要上采样。
举个例子,请考虑如下两个dfs:
>>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()
.
并且 df2 使用 resample(rule).mean()
下采样 到长度 6。
更新:
如果我可以将所有文件上采样到 179,那也很好。
我认为问题是当您在上采样情况下执行 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
时,它实际上仅使用第一个值进行插值,这意味着第一个值在所有行中都是 "repeated"
为了得到你想要的结果,那么在插值之前,即使在上采样的情况下也使用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
不会影响下采样情况下的结果。
这是我使用 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
我有许多长度在 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 不起作用。它只是 returns 个长度为 100 的数据帧,每列的第一个值刚刚复制到所有行。
我需要的是将它们全部设为 104(平均尺寸)。这意味着任何长度>104 的 df 都需要下采样,任何长度<104 的 df 都需要上采样。
举个例子,请考虑如下两个dfs:
>>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()
.
并且 df2 使用 resample(rule).mean()
下采样 到长度 6。
更新:
如果我可以将所有文件上采样到 179,那也很好。
我认为问题是当您在上采样情况下执行 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
时,它实际上仅使用第一个值进行插值,这意味着第一个值在所有行中都是 "repeated"
为了得到你想要的结果,那么在插值之前,即使在上采样的情况下也使用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
不会影响下采样情况下的结果。
这是我使用 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