在使用pandas TimeSeries的特定时间戳之后选择第一个索引

Art*_* B. 5 python lazy-evaluation pandas

这是一个由两部分组成的问题,有一个直接的问题和一个更普遍的问题.

我有一只熊猫TimeSeries,ts.要知道一定时间后的第一个值.我可以做这个,

ts.ix[ts[datetime(2012,1,1,15,0,0):].first_valid_index()]
Run Code Online (Sandbox Code Playgroud)

a)有更好,更少笨重的方法吗?

b)来自C,在处理这些有些不透明,可能是可变的但通常不是,可能是懒惰但不总是类型时,我有一定的恐惧症.所以要清楚,当我这样做

ts[datetime(2012,1,1,15,0,0):].first_valid_index()
Run Code Online (Sandbox Code Playgroud)

ts [datetime(2012,1,1,15,0,0):]是一个pandas.TimeSeries对象吗?我可能会改变它.

这是否意味着每当我拿一片时,都会在内存中分配一份ts副本?这是否意味着这个无害的代码行实际上只是为了获得索引值而触发一个千兆字节的TimeSeries副本?

或者他们可能神奇地共享内存,如果其中一个对象发生变异,则会完成一个懒惰的副本?但是,您如何知道哪些特定操作会触发副本?也许不切片,但如何重命名列?它似乎在文档中没有这么说.那会麻烦你吗?它应该打扰我还是我应该学会不用担心并发现探查器的问题?

Ama*_*man 12

一些设置:

In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: from datetime import datetime
In [4]: dates = [datetime(2011, 1, 2), datetime(2011, 1, 5), datetime(2011, 1, 7), datetime(2011, 1, 8), datetime(2011, 1, 10), datetime(2011, 1, 12)]

In [5]: ts = pd.Series(np.random.randn(6), index=dates)

In [6]: ts
Out[6]: 
2011-01-02   -0.412335
2011-01-05   -0.809092
2011-01-07   -0.442320
2011-01-08   -0.337281
2011-01-10    0.522765
2011-01-12    1.559876
Run Code Online (Sandbox Code Playgroud)

好的,现在回答你的第一个问题,a)是的,根据你的意图,不那么笨重的方法.这很简单:

In [9]: ts[datetime(2011, 1, 8):]
Out[9]: 
2011-01-08   -0.337281
2011-01-10    0.522765
2011-01-12    1.559876
Run Code Online (Sandbox Code Playgroud)

这是一个包含所选日期后所有值的切片.您可以按照自己的意愿选择第一个:

In [10]: ts[datetime(2011, 1, 8):][0]
Out[10]: -0.33728079849770815
Run Code Online (Sandbox Code Playgroud)

对于你的第二个问题,(b) - 这种类型的索引是原始的一部分,就像其他numpy数组一样.它不是原件的副本.看到这个问题,或许多类似的问题: Bug或功能:克隆一个带有切片的numpy数组

为了演示,让我们修改切片:

In [21]: ts2 = ts[datetime(2011, 1, 8):]
In [23]: ts2[0] = 99
Run Code Online (Sandbox Code Playgroud)

这会更改原始时间序列对象ts,因为ts2是切片而不是副本.

In [24]: ts
Out[24]: 
2011-01-02    -0.412335
2011-01-05    -0.809092
2011-01-07    -0.442320
2011-01-08    99.000000
2011-01-10     0.522765
2011-01-12     1.559876
Run Code Online (Sandbox Code Playgroud)

如果你想要一份副本,你可以(通常)使用复制方法,或者(在这种情况下)使用truncate:

In [25]: ts3 = ts.truncate(before='2011-01-08')

In [26]: ts3  
Out[26]: 
2011-01-08    99.000000
2011-01-10     0.522765
2011-01-12     1.559876
Run Code Online (Sandbox Code Playgroud)

更改此副本不会更改原始副本.

In [27]: ts3[1] = 99

In [28]: ts3
Out[28]: 
2011-01-08    99.000000
2011-01-10    99.000000
2011-01-12     1.559876

In [29]: ts                #The january 10th value will be unchanged. 
Out[29]: 
2011-01-02    -0.412335
2011-01-05    -0.809092
2011-01-07    -0.442320
2011-01-08    99.000000
2011-01-10     0.522765
2011-01-12     1.559876
Run Code Online (Sandbox Code Playgroud)

这个例子直接来自Wes的"Python for Data Analysis".看看这个.这很棒.