我需要从一个用Freq:120T索引的数据帧中切出几个间隔。每个所需间隔的开始日期由用Freq:None索引的第二个数据帧给出。我的想法是,我需要考虑每个开始日期,并包括构建每个间隔的时间和周期数。所有时间间隔的时间属性和时间段都相同。
让我们看看这个混乱的例子
假设我们的开始时间是'18:00:00',我们的周期数是3.要切片的数据帧是df1,包含开始日期的数据帧是df2。
df1
A B
DateTime
2005-09-06 16:00:00 1 5
2005-09-06 18:00:00 2 6
2005-09-06 20:00:00 3 7
2005-09-06 22:00:00 4 8
2005-12-07 16:00:00 9 8
2005-12-07 18:00:00 7 6
2005-12-07 20:00:00 5 4
2005-12-07 22:00:00 3 2
<class 'pandas.tseries.index.DatetimeIndex'>
[2005-09-06 16:00:00, ..., 2005-12-07 22:00:00]
Length: 8, Freq: 120T, Timezone: None
df2
Num
DateTime
2005-09-07 1
2005-12-07 2
<class 'pandas.tseries.index.DatetimeIndex'>
[2005-09-07, 2005-12-07]
Length: 2, Freq: None, Timezone: None
期望的输出:
df3 = func(source=df1['B'], start_dates=df2.index, time_start='18:00:00', periods=3)
1 2
18:00:00 6 6
20:00:00 7 4
22:00:00 8 2
我做了什么和考虑因素:
其中一个困难是df1中的数据频率为120T,但仅为工作日。考虑到这一点,我会做这样的事情:
start = df2.index[0] ## And somehow add to this formula the fact that we want to start at
'18:00'
df3 = df1['B'][(df1.index > start) & (df1.index < start + 3)] ## Somehow iterate this over the
dates in the df2 index
我感谢任何见解
提前致谢
答案 0 :(得分:2)
您正在寻找pivot ...至少在您提取了您感兴趣的行后。
In [11]: res = df.loc[df.index.normalize().isin(df2.index), 'B']
In [12]: res
Out[12]:
2005-09-06 16:00:00 5
2005-09-06 18:00:00 6
2005-09-06 20:00:00 7
2005-09-06 22:00:00 8
2005-12-07 16:00:00 8
2005-12-07 18:00:00 6
2005-12-07 20:00:00 4
2005-12-07 22:00:00 2
Name: B, dtype: int64
一旦它以该形式转移(如果可能缺少数据,您可能必须使用pivot_table
,这会更灵活一点)!
In [14]: pd.pivot(res.index.time, res.index.normalize(), res.values)
Out[14]:
2005-09-06 2005-12-07
16:00:00 5 8
18:00:00 6 6
20:00:00 7 4
22:00:00 8 2
&#34;肉&#34;使用isin进行行选择,检查标准化为午夜的时间是否包含在df2.index中。
df.index.normalize().isin(df2.index)
如果我们也关心时间,我们可以使用indexer_between_time
:
In [15]: df.ix[df.index.indexer_between_time('18:00', '00:00'), 'B']
Out[15]:
2005-09-06 18:00:00 6
2005-09-06 20:00:00 7
2005-09-06 22:00:00 8
2005-12-07 18:00:00 6
2005-12-07 20:00:00 4
2005-12-07 22:00:00 2
Name: B, dtype: int64
好的,在这个例子中它们是相同的(因为只有我们想要的日期!),但一般来说你真的想要这两个条件(到&#34;和&#34;它们)...
# I had tried to make this a one-liner but utterly failed!
in_time = np.zeros(len(df), dtype=bool)
in_time[df.index.indexer_between_time('18:00', '00:00')] = True
res = df.loc[df.index.normalize().isin(df2.index) & in_time, 'B']
In [17]: res
Out[17]:
2005-09-06 16:00:00 5
2005-09-06 18:00:00 6
2005-09-06 20:00:00 7
2005-09-06 22:00:00 8
2005-12-07 16:00:00 8
2005-12-07 18:00:00 6
Name: B, dtype: int64
您可以映射透视结果的列:
In [21]: pv = pd.pivot(res.index.time, res.index.normalize(), res.values)
In [22]: pv
Out[22]:
2005-09-06 2005-12-07
18:00:00 6 6
20:00:00 7 4
22:00:00 8 2
In [23]: pv.columns = pv.columns.map(df2.Num.get)
In [24]: pv
Out[24]:
1 2
18:00:00 6 6
20:00:00 7 4
22:00:00 8 2
瞧。
答案 1 :(得分:1)
完全不同的方法:
def next_n_asof(x, t, n):
"""The next n rows after time t in x
"""
i = np.argmax(df.index >= t)
return x[i:i + n]
In [11]: next_n_asof(df.B, pd.Timestamp('2005-09-06 18:00:00'), 3)
Out[11]:
2005-09-06 18:00:00 6
2005-09-06 20:00:00 7
2005-09-06 22:00:00 8
Name: B, dtype: int64
我们可以在索引中的每一天的concat中使用它:
In [12]: pd.concat(next_n_asof(df.B, t, 3)
for t in df2.index + pd.tseries.timedeltas.to_timedelta(18, unit='h'))
Out[12]:
2005-09-06 18:00:00 6
2005-09-06 20:00:00 7
2005-09-06 22:00:00 8
2005-12-07 18:00:00 6
2005-12-07 20:00:00 4
2005-12-07 22:00:00 2
Name: B, dtype: int64
我们必须在df2.index中添加时间:
In [13]: df2.index + pd.tseries.timedeltas.to_timedelta(18, unit='h')
Out[13]:
<class 'pandas.tseries.index.DatetimeIndex'>
[2005-09-06 18:00:00, 2005-12-07 18:00:00]
Length: 2, Freq: None, Timezone: None
注意:我无法让自己干净利落地工作......这可能会更有效率。