2016-05-29 25 views
5

Tôi có các khung dữ liệu với các chỉ số DateTime các loại khác nhau (có thể là dữ liệu hàng tuần, hàng tháng, hàng năm). Tôi muốn tạo các cột có giá trị trễ của các cột khác. Tôi nhận được những nhập khẩu từ một bảng tính, tôi không tạo ra các chỉ số datetime bên trong python.Cách Pythonic để làm trễ các cột được lập chỉ mục thời gian

Tôi đang đấu tranh để tìm cách 'pythonic' để thực hiện việc này. Tôi tính nếu tôi sử dụng khả năng datetime của Pandas, sự chậm trễ có thể mạnh mẽ hơn trong trường hợp dữ liệu lạ hoặc đặc biệt.

Tôi đã tạo một ví dụ đồ chơi có vẻ hoạt động, nhưng nó không thành công trên ví dụ thực tế của tôi.

Ví dụ đồ chơi mà hoạt động chính xác (làm cho một cột mới có giá trị 'foo' của tháng trước)

rng = pd.date_range('2012-01-01', '2013-1-01', freq="M") 
toy2 = pd.DataFrame(pd.Series(np.random.randint(0, 50, len(rng)), index=rng, name="foo")) 

      foo 
2012-01-31 4 
2012-02-29 2 
2012-03-31 27 
2012-04-30 7 
2012-05-31 44 
2012-06-30 22 
2012-07-31 16 
2012-08-31 18 
2012-09-30 35 
2012-10-31 35 
2012-11-30 16 
2012-12-31 32 

toy2['lag_foo']= toy2['foo'].shift(1,'m') 

    foo lag_foo 
2012-01-31 4 NaN 
2012-02-29 2 4.0 
2012-03-31 27 2.0 
2012-04-30 7 27.0 
2012-05-31 44 7.0 
2012-06-30 22 44.0 
2012-07-31 16 22.0 
2012-08-31 18 16.0 
2012-09-30 35 18.0 
2012-10-31 35 35.0 
2012-11-30 16 35.0 
2012-12-31 32 16.0 

Nhưng khi tôi chạy trên ví dụ thực tế cuộc sống của tôi, nó không thành công với:

ValueError: cannot reindex from a duplicate axis

print type(toy) 
print toy.columns 
print toy['IPE m2'][0:5] 

<class 'pandas.core.frame.DataFrame'> 
Index([u'IPE m2'], dtype='object') 
Date 
2016-04-30 43.29 
2016-03-31 40.44 
2016-02-29 34.17 
2016-01-31 32.47 
2015-12-31 39.35 
Name: IPE m2, dtype: float64 

ngoại lệ dấu vết:

ValueError        Traceback (most recent call last) 
<ipython-input-170-9cb57a2ed681> in <module>() 
----> 1 toy['prev_1m']= toy['IPE m2'].shift(1,'m') 

C:\Users\mds\Anaconda2\lib\site-packages\pandas\core\frame.pyc in __setitem__(self, key, value) 
    2355   else: 
    2356    # set column 
-> 2357    self._set_item(key, value) 
    2358 
    2359  def _setitem_slice(self, key, value): 

C:\Users\mds\Anaconda2\lib\site-packages\pandas\core\frame.pyc in _set_item(self, key, value) 
    2421 
    2422   self._ensure_valid_index(value) 
-> 2423   value = self._sanitize_column(key, value) 
    2424   NDFrame._set_item(self, key, value) 
    2425 

C:\Users\mds\Anaconda2\lib\site-packages\pandas\core\frame.pyc in _sanitize_column(self, key, value) 
    2555 
    2556   if isinstance(value, Series): 
-> 2557    value = reindexer(value) 
    2558 
    2559   elif isinstance(value, DataFrame): 

C:\Users\mds\Anaconda2\lib\site-packages\pandas\core\frame.pyc in reindexer(value) 
    2547      # duplicate axis 
    2548      if not value.index.is_unique: 
-> 2549       raise e 
    2550 
    2551      # other 

ValueError: cannot reindex from a duplicate axis 

Có vẻ như tôi đang thiếu một số tinh tế của các chỉ số thời gian của Pandas mà tôi nghĩ. Plus Tôi thậm chí không chắc chắn đây là cách lý tưởng để làm điều này. điều duy nhất tôi có thể nghi ngờ là toy.index không làm việc có Không như các kim loại, trong khi làm việc toy2 Ví dụ, có tần số của nó đặt là 'M'

toy.index 
DatetimeIndex(['2016-04-30', '2016-03-31', '2016-02-29', '2016-01-31', 
       '2015-12-31', '2015-11-30', '2015-10-31', '2015-09-30', 
       '2015-08-31', '2015-07-31', 
       ... 
         'NaT',  'NaT',  'NaT',  'NaT', 
         'NaT',  'NaT',  'NaT',  'NaT', 
         'NaT',  'NaT'], 
       dtype='datetime64[ns]', name=u'Date', length=142, freq=None) 


toy2.index 
DatetimeIndex(['2012-01-31', '2012-02-29', '2012-03-31', '2012-04-30', 
       '2012-05-31', '2012-06-30', '2012-07-31', '2012-08-31', 
       '2012-09-30', '2012-10-31', '2012-11-30', '2012-12-31'], 
       dtype='datetime64[ns]', freq='M') 
In [ ]: 

======== ===================

tôi ném đi của NAT

toy = toy.dropna() 

toy['prev_1m']= toy['IPE m2'].shift(1,'m') 

và tôi làm có được kết quả tôi muốn. Tuy nhiên, tôi cũng có được một cảnh báo:

C:\Users\mds\Anaconda2\lib\site-packages\ipykernel\__main__.py:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame. 
Try using .loc[row_indexer,col_indexer] = value instead 

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy 
    if __name__ == '__main__': 

====

cách này của nhiệm vụ ngăn chặn những lời cảnh báo:

toy.loc[:,'prev_1m2']= toy['IPE m2'].shift(1,'m') 

Trả lời

2

Có một vấn đề - nhiều NaT trong chỉ mục trong toyDataFrame , do đó, index có giá trị trùng lặp. (Có lẽ một số datetime được nhân đôi quá.)

mẫu:

import pandas as pd 
import numpy as np 

rng = pd.date_range('2012-01-01', '2013-1-01', freq="M") 
toy2 = pd.DataFrame(pd.Series(np.random.randint(0, 50, len(rng)), index=rng, name="foo")) 

df = pd.DataFrame({'foo': [10,30,19]}, index=[np.nan, np.nan, np.nan]) 
print (df) 
    foo 
NaN 10 
NaN 30 
NaN 19 

toy2 = pd.concat([toy2, df]) 
print (toy2) 
      foo 
2012-01-31 18 
2012-02-29 34 
2012-03-31 43 
2012-04-30 17 
2012-05-31 45 
2012-06-30 8 
2012-07-31 36 
2012-08-31 26 
2012-09-30 5 
2012-10-31 18 
2012-11-30 39 
2012-12-31 3 
NaT   10 
NaT   30 
NaT   19 

toy2['lag_foo']= toy2['foo'].shift(1,'m') 
print (toy2) 

ValueError: cannot reindex from a duplicate axis

tham số

Một giải pháp khả thi có thể được bỏ qua freq=m:

toy2['lag_foo']= toy2['foo'].shift(1) 
print (toy2) 
      foo lag_foo 
2012-01-31 21  NaN 
2012-02-29 13  21.0 
2012-03-31 41  13.0 
2012-04-30 38  41.0 
2012-05-31 15  38.0 
2012-06-30 41  15.0 
2012-07-31 30  41.0 
2012-08-31 18  30.0 
2012-09-30 12  18.0 
2012-10-31 35  12.0 
2012-11-30 23  35.0 
2012-12-31 7  23.0 
NaT   10  7.0 
NaT   30  10.0 
NaT   19  30.0 

Nếu cần loại bỏ tất cả hồ sơ với NaN (NaT) trong index, sử dụng notnull với boolean indexing:

print (toy2) 
      foo 
2012-01-31 41 
2012-02-29 15 
2012-03-31 8 
2012-04-30 2 
2012-05-31 16 
2012-06-30 43 
2012-07-31 2 
2012-08-31 15 
2012-09-30 3 
2012-10-31 46 
2012-11-30 34 
2012-12-31 36 
NaT   10 
NaT   30 
NaT   19 

toy2 = toy2[pd.notnull(toy2.index)] 

toy2['lag_foo']= toy2['foo'].shift(1, 'm') 
print (toy2) 
      foo lag_foo 
2012-01-31 41  NaN 
2012-02-29 15  41.0 
2012-03-31 8  15.0 
2012-04-30 2  8.0 
2012-05-31 16  2.0 
2012-06-30 43  16.0 
2012-07-31 2  43.0 
2012-08-31 15  2.0 
2012-09-30 3  15.0 
2012-10-31 46  3.0 
2012-11-30 34  46.0 
2012-12-31 36  34.0 
+0

Tôi đã sử dụng dropna() để loại bỏ các NaT, và nó hoạt động, tuy nhiên nó đưa ra một số cảnh báo. Đã thêm phụ lục cho câu hỏi gốc. – user3556757

+1

Bạn có chắc là bạn cần 'dropna'? Nó loại bỏ tất cả các hàng có 'NaN' trong cột. Nếu có, sử dụng' copy': 'toy = toy.dropna(). Copy()' Nếu cần xóa các bản ghi với 'NaN' trong chỉ mục, sử dụng' toy = toy [ pd.notnull (toy.index)] '. – jezrael

Các vấn đề liên quan