这是一个由两部分组成的问题,有一个直接的问题和一个更一般的问题。
我有一只熊猫TimeSeries,ts。知道一段时间后的第一个值。我能做这些,
ts.ix[ts[datetime(2012,1,1,15,0,0):].first_valid_index()]a)有没有更好的、不那么笨拙的方法?
b)来自C语言的我,在处理这些有点不透明、可能可变但通常不是、可能懒惰但并不总是的类型时,我有一定的恐惧症。所以说清楚,当我这样做的时候
ts[datetime(2012,1,1,15,0,0):].first_valid_index()tsdatetime(2012,1,1,15,0,0):pandas.TimeSeries对象对吗?我可能会让它发生变异。
这是不是意味着每当我取一个切片时,内存中就会分配一个ts的副本?这是否意味着这一行无伤大雅的代码实际上可以触发一个千兆字节的TimeSeries副本,仅仅是为了获得一个索引值?
或者,也许它们神奇地共享内存,例如,如果其中一个对象发生突变,就会进行延迟复制?但是,您如何知道哪些特定操作会触发复制呢?也许不是切片,但是如何重命名列呢?在文档中似乎没有这样说。这让你很困扰吗?它应该困扰我,还是我应该学会不用担心,并用分析器捕捉问题?
发布于 2012-10-24 07:16:19
一些设置:
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好的,现在回答你的第一个问题,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这是一个切片,包含所选日期之后的所有值。根据需要,您可以通过以下方式仅选择第一个:
In [10]: ts[datetime(2011, 1, 8):][0]
Out[10]: -0.33728079849770815关于您的第二个问题,(b) --这种类型的索引是原始索引的一部分,就像其他numpy数组一样。它不是原件的复制品。查看这个问题,或许多类似的问题:Bug or feature: cloning a numpy array w/ slicing
为了演示,让我们修改切片:
In [21]: ts2 = ts[datetime(2011, 1, 8):]
In [23]: ts2[0] = 99这会更改原始的timeseries对象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如果您确实需要一个副本,您可以(通常)使用copy方法,或者(在本例中)使用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更改此副本不会更改原始副本。
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这个例子直接取自Wes的"Python for Data Analysis“。看看这个。太棒了。
发布于 2012-10-24 06:54:33
我不认识熊猫,一般的答案是:
你可以在python中重载任何东西,他们肯定已经在那里做过了。如果您在您的类上定义了一个特殊的方法__getitem__,那么当您使用obj[key]或obj[start:stop] (在前一种情况下只使用__getitem__作为参数,在后一种情况下使用特殊的slice object )时,就会调用它。然后你可以返回任何你想要的东西。
下面的例子展示了__getitem__是如何工作的:
class Foo(object):
def __getitem__(self, k):
if isinstance(k, slice):
return k.start + k.stop # properties of the slice object
else:
return k这为您提供了:
>>> f = range.Foo()
>>> f[42]
42
>>> f[23:42]
65我假设在您的示例中,__getitem__方法返回一些特殊的对象,其中包含datetime对象以及对原始ts对象的引用。然后,当调用first_valid_index方法或类似方法时,该特殊对象可以使用该信息来获取所需的信息。(它甚至不必修改原始对象,就像您的问题所建议的那样。)
TL;DR:学会不要担心:-)
Addition:我很好奇,所以我自己实现了一个你上面描述的行为的最小示例:
class FilterableList(list):
def __init__(self, *args):
list.__init__(self, *args)
self.filter = FilterProxy(self)
class FilterProxy(object):
def __init__(self, parent):
self.parent = parent
def __getitem__(self, sl):
if isinstance(sl, slice):
return Filter(self.parent, sl)
class Filter(object):
def __init__(self, parent, sl):
self.parent = parent
self.sl = sl
def eval(self):
return [e for e in self.parent if self.sl.start <= e <= self.sl.stop]
>>> l = FilterableList([4,5,6,7])
>>> f = l.filter[6:10]
>>> f.eval()
[6, 7]
>>> l.append(8)
>>> f.eval()
[6, 7, 8]https://stackoverflow.com/questions/13040312
复制相似问题