import pandas as pd
import numpy as np
import datetime
from pandas_datareader import data, wb

pd.set_eng_float_format(accuracy=2, use_eng_prefix=True)

my_first_panel = pd.Panel(np.random.randn(2, 5, 4), 
                          items=['Item01', 'Item02'],
                          major_axis=pd.date_range('9/6/2016', periods=5),
                          minor_axis=['A', 'B', 'C', 'D'])
my_first_panel

"""
Explanation: Creating Panels
A Panel is a three-dimensional analogue of DataFrame.  Each item (the analogue of columns in a DataFrame) in a Panel is a DataFrame.
The term panel data is derived
from econometrics and is partially responsible for the name pandas: pan(el)-da(ta)-s. The names for the 3 axes within a panel are intended to give some semantic meaning to describing operations involving panel data and, in particular, econometric
analysis of panel data. However, for the strict purposes of slicing and dicing a collection of DataFrame objects, you
may find the axis names slightly arbitrary:

items: axis 0, each item corresponds to a DataFrame contained inside
major_axis: axis 1, it is the index (rows) of each of the DataFrames
minor_axis: axis 2, it is the columns of each of the DataFrames

source: http://pandas.pydata.org/pandas-docs/stable/dsintro.html#panel
End of explanation
"""


dictionary_of_data_frames = {'Item1' : pd.DataFrame(np.random.randn(4, 3)),
                             'Item2' : pd.DataFrame(np.random.randn(4, 2))}
my_dictionary_panel = pd.Panel(dictionary_of_data_frames)
my_dictionary_panel

"""
Explanation: From dict of DataFrame objects
Note that the values in the dict need only be convertible to DataFrame.
End of explanation
"""


oriented_panel = pd.Panel.from_dict(dictionary_of_data_frames, orient='minor')
oriented_panel

"""
Explanation: Panel.from_dict()
One helpful factory method is Panel.from_dict, which takes a dictionary of DataFrames, and has the following named parameters:
| Parameter | Default | Description                                         |
|-----------|---------|-----------------------------------------------------|
| intersect | False   | drops elements whose indices do not align           |
| orient    | items   | use minor to use DataFrames’ columns as panel items |
Orient is especially useful for mixed-type DataFrames. If you pass a dict of DataFrame objects with mixed-type columns, all of the data will get upcasted to dtype=object unless you pass orient='minor':
End of explanation
"""


start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2016, 7, 15)
pdata = pd.Panel(dict((stk, data.DataReader("F", 'yahoo', start, end))
for stk in ['AAPL', 'GOOG', 'MSFT', 'DELL']))

pdata

"""
Explanation: Panels using remote stock data
source: Python for Data Analysis by Wes McKinney page 152; modified by Charles Kelly to use DataReader
End of explanation
"""


pdata = pdata.swapaxes('items', 'minor')

pdata['Adj Close'].head()

"""
Explanation: swap axes: make the stocks the columns
documentation: http://pandas.pydata.org/pandas-docs/version/0.18.0/generated/pandas.Panel.swapaxes.html
End of explanation
"""


pdata.ix[:, '7/12/2016', :]

"""
Explanation: NumPy ix generalizes to three dimensions
source: http://docs.scipy.org/doc/numpy/reference/generated/numpy.ix_.html
End of explanation
"""


stacked = pdata.ix[:, '6/30/2016':, :].to_frame()
print(type(stacked))
stacked

"""
Explanation: convert Panel to DataFrame with multi-index
End of explanation
"""


stacked.to_panel()

"""
Explanation: convert DataFrame with multi-index to a Panel
End of explanation
"""


