Python 数据帧中间隔的高级切片

Python 数据帧中间隔的高级切片,python,pandas,time-series,dataframe,subset,Python,Pandas,Time Series,Dataframe,Subset,我需要从一个索引为Freq:120T的数据帧中切出几个间隔。每个期望间隔的开始日期由第二个数据帧给出,该数据帧使用Freq:None进行索引。我的想法是,我需要记录每个开始日期,并包括一个时间和#个时段来构建每个间隔。时间属性和时段对于所有间隔都是相同的 让我们用一个例子来看看这个混乱 假设我们的开始时间是“18:00:00”,我们的周期数是3。要切片的数据帧是df1,包含开始日期的数据帧是df2 df1 我做了哪些工作和考虑: 困难之一是df1中的数据频率为120T,但仅为工作日。考虑到这一点

我需要从一个索引为Freq:120T的数据帧中切出几个间隔。每个期望间隔的开始日期由第二个数据帧给出,该数据帧使用Freq:None进行索引。我的想法是,我需要记录每个开始日期,并包括一个时间和#个时段来构建每个间隔。时间属性和时段对于所有间隔都是相同的

让我们用一个例子来看看这个混乱

假设我们的开始时间是“18:00:00”,我们的周期数是3。要切片的数据帧是df1,包含开始日期的数据帧是df2

df1

我做了哪些工作和考虑:

困难之一是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
start=df2.index[0]###并以某种方式将我们希望从
'18:00'
df3=df1['B'][(df1.index>start)&(df1.index
我很欣赏你的见解

提前感谢

您正在寻找。。。至少在提取了感兴趣的行之后

在同一日期、使用和:

一旦它以这种形式出现,就要转移(如果有可能丢失数据,您可能必须使用更灵活的数据)

使用isin选择行的“肉”,检查标准化为午夜的时间是否包含在df2.index中

df.index.normalize().isin(df2.index)

如果我们也关心我们可以利用的时间:

好的,在这个例子中,这些条件是相同的(因为只有我们想要的日期!),但是通常你真的想要这两个条件(去“和”它们)


可以映射数据透视结果的列:

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

瞧。

一种完全不同的方法:

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
[13]中的
:df2.index+pd.tseries.timedelta.to_timedelta(18,unit='h')
出[13]:
[2005-09-06 18:00:00, 2005-12-07 18:00:00]
长度:2,频率:无,时区:无

注意:我无法让它与asof本身一起干净地工作。。。哪个可能更有效。

你能举一个小例子来说明这一点吗,一个包含39433个条目的例子似乎有点极端(我不明白你想做什么)@安迪·海登,你可以忽略这个数字。简化的示例是,如果df1包含示例的8行。考虑到df2的开始时间戳,我试图提取df1的片段。让我知道这是否更清楚。谢谢,汉克斯,那简单多了。我仍然不知道如何从df1和df2中获得df3,但可能对我来说太晚了@Andy Hayden注意到df3有两个等长的df1数据间隔,每个间隔都从df2.index中的日期开始。就像df1有粒度数据(更高的频率),df2给你日期。这个解决方案几乎是完美的。有一个问题,请记住,在我提到的问题中,我需要指定一个小时(您提到的)和一个时段。为什么是周期?因为间隔可能是多天的,而且数据在工作日内,或者在这两个工作日之间缺少一些数据。在我看来,通过使用“中间时间”,代码被优化为“当天”工作。如果这是一个让人头疼的问题,我很抱歉。我试图在问题中表达这种担忧,并提供了一个简单的例子。也许我失败了。如果你能更新答案,我将不胜感激。@hernanavella这实际上不是白天,你可以在18:00到02:00之间做。我不太清楚你要说什么。我想你的意思是你想在日期和时间dt之后选择下一个(?)时间(对于几个具有相同开始时间的日期),然后选择随后的N条记录(包括)?如果这是你的意思,你可以使用.asof。是的,后面的N个记录。如果您注意到在示例中,我们说从“18:00”开始,并包含3条以上的记录,那么您从“18:00”抓取到了“22:00”“。在您编写的脚本中,我如何告诉函数抓取,比如说随后的36条记录?它工作正常,感谢您的努力。这是一个棘手的问题。现在我只需要获取df并将其旋转。当我将df的频率从1小时更改为2小时时,该功能会停止,并给出空的数据帧。我不知道如何使它灵活地适应测向频率。有什么线索吗?@hernanavella不太清楚你是怎么看的,这在任何地方都没有使用频率?我知道,这是我的问题。如果我在df.B freq=None的情况下运行该函数,它就可以正常工作。如果我用df.B freq='120T'运行它,它会给我一个空的数据帧。@hernanavella,这很奇怪。也许可以将其作为一个单独的问题发布,并附上一个失败的例子。我不知道这是怎么回事!
df.index.normalize().isin(df2.index)
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
# 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
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
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
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