python - 什么是组合相关但存储在不同数据帧中的数据集的好设计模式?

标签 python pandas oop data-structures functional-programming

假设我们要构建一个股票投资组合。为了决定将哪些股票包含在投资组合中以及为这些股票分配什么权重,我们使用不同的指标,例如价格、每股 yield (eps)、股息 yield 等......所有这些指标都存储在单个 Pandas 数据框,其中行指定特定时间点,列与特定股票相关联(例如,IBM、MSFT 等):

import pandas as pd

price = pd.DataFrame([[-1.332298,  0.396217,  0.574269, -0.679972, -0.470584,  0.234379],
                      [-0.222567,  0.281202, -0.505856, -1.392477,  0.941539,  0.974867],
                      [-1.139867, -0.458111, -0.999498,  1.920840,  0.478174, -0.315904],
                      [-0.189720, -0.542432, -0.471642,  1.506206, -1.506439,  0.301714]],
                     columns=['IBM', 'MSFT', 'APPL', 'ORCL','FB','TWTR'], 
                     index=pd.date_range('2000', freq='D', periods=4))

eps = pd.DataFrame([[-1.91,  1.63,  0.51, -.32, -0.84,  0.37],
                      [-0.56,  0.02, 0.56, 1.77,  0.99,  0.97],
                      [-1.67, -0.41, -0.98,  1.20,  0.74, -0.04],
                      [-0.80, -0.43, -0.12,  1.06, 1.59,  0.34]],
                     columns=['IBM', 'MSFT', 'APPL', 'ORCL','FB','TWTR'], 
                     index=pd.date_range('2000', freq='D', periods=4))


price

    IBM MSFT    APPL    ORCL    FB  TWTR
2000-01-01  -1.332298   0.396217    0.574269    -0.679972   -0.470584   0.234379
2000-01-02  -0.222567   0.281202    -0.505856   -1.392477   0.941539    0.974867
2000-01-03  -1.139867   -0.458111   -0.999498   1.920840    0.478174    -0.315904
2000-01-04  -0.189720   -0.542432   -0.471642   1.506206    -1.506439   0.301714


eps

    IBM MSFT    APPL    ORCL    FB  TWTR
2000-01-01  -1.91   1.63    0.51    -0.32   -0.84   0.37
2000-01-02  -0.56   0.02    0.56    1.77    0.99    0.97
2000-01-03  -1.67   -0.41   -0.98   1.20    0.74    -0.04
2000-01-04  -0.80   -0.43   -0.12   1.06    1.59    0.34

不同的数据帧显然是紧密相连的。但是,它们都存储在单独的变量中。在大型应用程序中,很难跟踪哪些变量属于一起并形成一个连贯的单元。安排此类相关数据集的良好设计范式是什么?
使用面向对象的设计模式,我将构造类似 StockList() 对象的东西,该对象存储单个 Stock() 对象,该对象又存储与特定股票对应的信息(时间序列)。
class Stock():
    def __init__(self, price_series, eps_series, div_yield_series):
        self.price = price_series
        self.eps = eps_series
        self.div_yield = div_yield_series

class  StockList():
    def __init__(self, stock_list):
        self.stock_list = stock_list
        
    def append(self, stock):
        self.stock_list.append(stock)


但是,在使用数据框时,这是一个可行的选择吗?我认为将时间序列分开并在查询时将它们合并在一起,会导致性能的显着损失和一组多余的操作。
或者, StockList() 可以直接存储数据帧,而无需构造单个 Stock() 对象(或多或少用作数据结构)。然而,这是一个适当的妥协吗?
我通常想知道是否应该创建一个单独的对象,或者是否应该将这些单独的数据帧作为单独的变量保留。这很可能会提高性能、减少内存使用、支持并行计算并培养函数式编程风格。
但是我们如何才能捆绑属于一起的数据呢?

最佳答案

此示例有 3 个度量,因此我将创建一个具有 3 级多索引的 Pandas 系列:

  • 公制(每股 yield ,价格)
  • 日期 (2000-01-01, 2000-01-02, ...)
  • 股票代码 ('AAPL', 'FB', ...)

  • 首先,根据原始帖子创建 eps 和 price 数据框:
    import pandas as pd
    
    price = pd.DataFrame([[-1.332298,  0.396217,  0.574269, -0.679972, -0.470584,  0.234379],
                          [-0.222567,  0.281202, -0.505856, -1.392477,  0.941539,  0.974867],
                          [-1.139867, -0.458111, -0.999498,  1.920840,  0.478174, -0.315904],
                          [-0.189720, -0.542432, -0.471642,  1.506206, -1.506439,  0.301714]],
                         columns=['IBM', 'MSFT', 'APPL', 'ORCL','FB','TWTR'], 
                         index=pd.date_range('2000', freq='D', periods=4))
    
    eps = pd.DataFrame([[-1.91,  1.63,  0.51, -.32, -0.84,  0.37],
                          [-0.56,  0.02, 0.56, 1.77,  0.99,  0.97],
                          [-1.67, -0.41, -0.98,  1.20,  0.74, -0.04],
                          [-0.80, -0.43, -0.12,  1.06, 1.59,  0.34]],
                         columns=['IBM', 'MSFT', 'APPL', 'ORCL','FB','TWTR'], 
                         index=pd.date_range('2000', freq='D', periods=4))
    
    其次,结合这些来创建新的股票表(具有多索引):
    # re-shape `eps` data frame
    eps.index.name = 'date'
    eps.columns.name = 'ticker'
    eps = (eps.assign(metric='eps')
           .set_index('metric', append=True)
           .stack()
           .swaplevel('metric', 'date')
           .sort_index()
          )
    
    # re-shape `price` data frame
    price.index.name = 'date'
    price.columns.name = 'ticker'
    price = (price.assign(metric='price')
             .set_index('metric', append=True)
             .stack()
             .swaplevel('metric', 'date')
             .sort_index())
    
    # you could put, say, `volume` data frame here...
    
    # concatenate
    stock_data = pd.concat([eps, price]).rename('value')
    
    # display
    print(stock_data.head(8))
    
    metric  date        ticker
    eps     2000-01-01  APPL      0.51
                        FB       -0.84
                        IBM      -1.91
                        MSFT      1.63
                        ORCL     -0.32
                        TWTR      0.37
            2000-01-02  APPL      0.56
                        FB        0.99
    Name: value, dtype: float64
    
    pandas MultiIndex 功能强大,但对于数据帧来说并不直观。对于系列来说,它更直接。一切都用 .loc[::] 指定.然后我们可以使用 .unstack()重新塑造以进行进一步的下游处理(例如,在行上创建带有日期的数据框,在列上创建股票代码,并使用 Matplotlib 创建绘图)
    # index level 0, scalar
    t0 = stock_data.loc['eps']
    
    # index level 1, range
    t1 = stock_data.loc[:, '2000-01-02':'2000-01-03']
    
    # index level 2, list
    t2 = stock_data.loc[:, :, ['AAPL', 'MSFT', 'TWTR']]
    

    关于python - 什么是组合相关但存储在不同数据帧中的数据集的好设计模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63174054/

    相关文章:

    PHP OOP - 尝试调用方法

    Python基础数学算法函数

    python - 使用朴素贝叶斯的两个字典之间的相似性概率

    python - Pandas 中更快的应用方法

    python - pandas df.apply TypeError 数据类型不理解

    python - 如何测试变量是否为 pd.NaT?

    java - 为另一个类做事的类

    .net 收藏 : how to copy objects from one collection to another?

    python - 如何将 intable 字符串列表转换为 int

    python - 将状态附加到 pandas 中的数据框