5

これは、即時の質問とより一般的な質問の 2 つの部分からなる質問です。

私はパンダの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()

ts[datetime(2012,1,1,15,0,0):] は pandas.TimeSeries オブジェクトですよね? そして、私はおそらくそれを変異させることができました.

スライスを取得するたびに、メモリに割り当てられている ts のコピーがあるということですか? この無害なコード行が、インデックス値を取得するためだけに、実際にギガバイトの TimeSeries のコピーをトリガーできるということですか?

それとも、魔法のようにメモリを共有し、たとえばオブジェクトの 1 つが変更された場合に遅延コピーが行われるのでしょうか? では、どの特定の操作がコピーをトリガーするかをどのように知るのでしょうか? スライスではないかもしれませんが、列の名前を変更するのはどうですか? ドキュメントにはそうは書かれていないようです。気になりますか?それは私を悩ませるべきですか、それとも心配しないでプロファイラーで問題をキャッチすることを学ぶべきですか?

4

2 に答える 2

13

いくつかのセットアップ:

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

さて、あなたの最初の質問に答えましょう。これは非常に簡単です:

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

2 番目の質問 (b) に対して、このタイプのインデックス付けは、他の numpy 配列と同様に、元のスライスです。オリジナルのコピーではありません。この質問、または同様の多くの質問を参照してください: バグまたは機能: numpy array w/ slicing のクローン作成

実証するために、スライスを変更してみましょう。

In [21]: ts2 = ts[datetime(2011, 1, 8):]
In [23]: ts2[0] = 99

ts2 はスライスでありコピーではないため、これにより元の timeseries オブジェクト ts が変更されます。

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-23T23:16:18.527 に答える
0

私はパンダを知らない、一般的な答え:

Pythonでは何でもオーバーロードできます。彼らはそこでそれを行ったに違いありません。クラスで特別なメソッドを定義すると、 or__getitem__を使用したときに呼び出されます(前者の場合は引数としてキーのみを使用し、後者の場合は特別なオブジェクトを使用)。その後、必要なものを返すことができます。obj[key]obj[start:stop]slice

がどのように機能するかを示す例を次に示します__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__メソッドは日時オブジェクトと元のオブジェクトへの参照を含む特別なオブジェクトを返すと思いtsます。first_valid_indexその特別なオブジェクトは、後でメソッドまたは同様のメソッドが呼び出されたときに、その情報を使用して必要な情報を取得できます。(あなたの質問が示唆したように、元のオブジェクトを変更する必要さえありません。)

TL;DR:心配しないことを学びましょう :-)

追加:興味があったので、上記の動作の最小限の例を自分で実装しました:

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]
于 2012-10-23T22:54:33.180 に答える