我需要根据以下两个条件拍摄时间序列数据框:
让我们看一个例子
df1 - 这是我们从
获取切片的地方 A B
DateTime
2011-01-02 00:00:00 1 2
2011-01-02 04:00:00 2 4
2011-01-02 08:00:00 3 5
2011-01-02 12:00:00 2 6
2011-01-02 16:00:00 5 6
2011-01-02 20:00:00 2 1
2011-01-03 00:00:00 5 2
2011-01-03 04:00:00 3 3
2011-01-03 08:00:00 2 2
2011-01-03 12:00:00 0 4
2011-01-03 16:00:00 5 4
2011-01-03 20:00:00 1 1
<class 'pandas.tseries.index.DatetimeIndex'>
[2011-01-02 00:00:00, ..., 2011-01-03 20:00:00]
Length: 12, Freq: 240T, Timezone: None
df2 - 这是切片开始的日期部分所在。
N
DateTime
2011-01-10 00:00:00 1
2011-03-10 00:00:00 2
<class 'pandas.tseries.index.DatetimeIndex'>
[2011-01-02, ..., 2011-01-03]
Length: 2, Freq: None, Timezone: None
假设我们想要df1['A']
的间隔length=4
,'04:00:00'
的每个时间间隔的开始时间df2
....所需的输出示例如下:
func(df1['A'], df2, lenght=4, start_time='04:00')
A
DateTime
2011-01-02 04:00:00 2
2011-01-02 08:00:00 3
2011-01-02 12:00:00 2
2011-01-02 16:00:00 5
2011-01-03 04:00:00 3
2011-01-03 08:00:00 2
2011-01-03 12:00:00 0
2011-01-03 16:00:00 5
需要考虑的事项:
我尝试了什么:
在这里有一些帮助我尝试了这种方法,但只有当df的频率都是“无”时才能正常工作。
def next_n_asof(x, t, n):
i = np.argmax(df1.index >= t)
return x[i:i + n]
pd.concat(next_n_asof(df1.A, t, 4)
for t in df2.index)
提前致谢
答案 0 :(得分:2)
next_n_asof
中的一个非常小的变化会产生预期的结果。如果不是
i = np.argmax(df1.index >= t)
你使用
i = np.argmax(df1.index > t)
然后您的代码生成
2011-01-02 04:00:00 2
2011-01-02 08:00:00 3
2011-01-02 12:00:00 2
2011-01-02 16:00:00 5
2011-01-03 04:00:00 3
2011-01-03 08:00:00 2
2011-01-03 12:00:00 0
2011-01-03 16:00:00 5
Name: A, dtype: int64
也许我误解了这个问题,因为这似乎太容易了。
尽管如此,这里有一个可能更快的替代方案:
请注意,此代码使用带有for-loop
次迭代的len(df2.index)
pd.concat(next_n_asof(df1.A, t, 4) for t in df2.index)
您可以改为使用
start = df1.index.get_indexer_for(df2.index)
查找df2.index
中的时间戳等于df1.index
中的时间戳的索引。例如,
In [93]: df1.index.get_indexer_for(df2.index)
Out[93]: array([0, 6])
使用DatetimeIndex的get_indexer_for
方法比使用此列表推导更快:
In [101]: [np.argmax(df1.index >= t) for t in df2.index]
Out[101]: [0, 6]
In [103]: %timeit [np.argmax(df1.index >= t) for t in df2.index]
10000 loops, best of 3: 85.5 µs per loop
In [104]: %timeit df1.index.get_indexer_for(df2.index)
100000 loops, best of 3: 14.5 µs per loop
从那里开始为你希望选择的df1
中的行创建所有所需索引的布尔掩码并不难:
mask = np.zeros(len(df), dtype='bool')
for i in range(length):
mask[start+i] = True
然后,您可以使用
从df1
中选择所需的行
df1.loc[mask]
而不是创建(可能)许多较小的DataFrame然后
将它们与pd.concat
连接起来,如果有很多子数据框,则速度较慢。
因此,此替代方法使用for-loop
次迭代交换len(df2.index)
对于for-loop
进行n=4
次迭代(在您提出的示例问题中)。如果是df2
但n
很小,这种替代方法应该更快。
import numpy as np
import pandas as pd
df1 = pd.DataFrame({'A': [1, 2, 3, 2, 5, 2, 5, 3, 2, 0, 5, 1],
'B': [2, 4, 5, 6, 6, 1, 2, 3, 2, 4, 4, 1]},
index=pd.date_range('2011-1-2', '2011-01-03 20:00', freq='240T'))
df2 = pd.DataFrame({'N': 1}, index=pd.date_range('2011-1-2', '2011-01-03'))
def next_n_asof(x, t, n):
i = np.argmax(df1.index > t)
return x[i:i + n]
print(pd.concat(next_n_asof(df1.A, t, 4)
for t in df2.index))
def func(df, index, length):
start = df.index.get_indexer_for(index)
mask = np.zeros(len(df), dtype='bool')
for i in range(length):
mask[start+i] = True
return df.loc[mask]
index = df2.index + pd.DateOffset(hour=4)
print(func(df1['A'], index, length=4))
产量
2011-01-02 04:00:00 2
2011-01-02 08:00:00 3
2011-01-02 12:00:00 2
2011-01-02 16:00:00 5
2011-01-03 04:00:00 3
2011-01-03 08:00:00 2
2011-01-03 12:00:00 0
2011-01-03 16:00:00 5
Name: A, dtype: int64