【问题标题】:Pandas Design Considerations for MultiIndexed Dataframes多索引数据帧的 Pandas 设计注意事项
【发布时间】:2016-12-16 07:44:44
【问题描述】:

这个问题的目的是进一步探索MultiIndex dataframes,并就各种任务的最佳方法提出问题。

创建数据框

import pandas as pd

df = pd.DataFrame({'index_date' : ['12/07/2016','12/07/2016','12/07/2016','12/07/2016','12/07/2016'], 
               'portfolio' : ['A','B','C','D','E'], 
               'reporting_ccy' : ['GBP','GBP','GBP','GBP','GBP'],
               'portfolio_ccy' : ['JPY','USD','USD','EUR','EUR'],
               'amount' : [100,200,300,400,500],
               'injection' : [1,2,3,4,5],
               'to_usd' : [1.3167,1.3167,1.3167,1.3167,1.3167],
               'to_ccy' : [0.009564,1,1,1.1093,1.1093],
               'm5' : [2,4,6,8,10],
               'm6' : [1,3,5,7,9]}); 

旋转数据框

df_pivot = df.pivot_table(index='index_date',columns=['portfolio','portfolio_ccy','reporting_ccy']).swaplevel(0, 1, axis=1).sortlevel(axis=1)

重命名列

df_pivot.columns.names = ['portfolio','measures', 'portfolio_ccy', 'reporting_ccy']

这会产生数据的旋转表示,这样:

  1. 一个投资组合可能有一个或多个度量
  2. 显示投资组合默认货币
  3. 显示投资组合报告货币
  4. 一个度量可能有一种或多种报告货币。

I 条款 4。鉴于我们有货币的 xRates,最好的实施方法是什么?

这样我们就可以创建一个类似于此处派生的数据框:

创建数据框

df1 = pd.DataFrame({'index_date' : ['12/07/2016','12/07/2016','12/07/2016','12/07/2016','12/07/2016'], 
           'portfolio' : ['A','B','C','D','E'], 
           'reporting_ccy' : ['JPY','USD','USD','EUR','EUR'],
           'portfolio_ccy' : ['JPY','USD','USD','EUR','EUR'],
           'amount' : [13767.2522, 263.34, 395.01, 474.785901, 593.4823763],
           'injection' : [1,2,3,4,5],
           'to_usd' : [0.009564, 1, 1, 1.1093, 1.1093],
           'to_ccy' : [1.3167, 1.3167, 1.3167, 1.3167, 1.3167],
           'm5' : [2,4,6,8,10],
           'm6' : [1,3,5,7,9]}); 

连接和旋转数据帧

df_concat = pd.concat([df,df1])
df_pivot1 = df_concat.pivot_table(index='index_date',columns=['portfolio','portfolio_ccy','reporting_ccy']).swaplevel(0, 1, axis=1).sortlevel(axis=1)
df_pivot1.columns.names = ['portfolio','measures', 'portfolio_ccy', 'reporting_ccy']

现在显示 1 个度量有多种货币。

df_pivot1.xs(('amount', 'A'), level=('measures','portfolio'), drop_level=False, axis=1)

问题

有没有更好的方法,比如直接将数据添加到级别 3 df_pivot1.columns.get_level_values(3).unique() 的多索引数据框?

我希望能够遍历每个级别并添加新的度量值,这些新度量值要么来自使用 df.assign() 或其他方法的其他度量值。

此处的用例是将其他货币添加到适用的度量中。上面的连接和重新旋转似乎不是最佳的。

【问题讨论】:

  • 这也在进一步探索here
  • 尽管这是一个格式正确的问题,但我对您的要求感到困惑。可能完全关闭,但您是否希望使用 df_pivot 并添加所有报告货币或其他内容?您可以使用 df(枢轴之前)这样做吗?
  • 我的意思是,在多索引数据框中添加到较低级别并不是一种简单的方法。我已经解决了这个问题,我认为我发布的其他问题对此进行了探索。这是在枢轴之后。原因是您可能有一个 MultiIndex,并希望添加从现有 Multi-Index 框架中的数据或其他数据源等中派生的其他度量。
  • 我仍然错过了我猜的重点。 df_pivot.ix['A','amount','JPY','GBP'] = 4 不会满足你的需要吗?
  • 您的示例不起作用,因为 df_pivot 与您所规定的结构不同。

标签: python pandas


【解决方案1】:

您可以将 df1 逐行附加到 df_pivot 上,而不是通过将两个帧连接在一起来重建枢轴。

与每次接收到新数据时从头开始连接和重建枢轴相比,追加到 DataFrame 的末尾会减少内存开销。

import pandas as pd

df = pd.DataFrame({'index_date' : ['12/07/2016','12/07/2016','12/07/2016','12/07/2016','12/07/2016'], 
               'portfolio' : ['A','B','C','D','E'], 
               'reporting_ccy' : ['GBP','GBP','GBP','GBP','GBP'],
               'portfolio_ccy' : ['JPY','USD','USD','EUR','EUR'],
               'amount' : [100,200,300,400,500],
               'injection' : [1,2,3,4,5],
               'to_usd' : [1.3167,1.3167,1.3167,1.3167,1.3167],
               'to_ccy' : [0.009564,1,1,1.1093,1.1093],
               'm5' : [2,4,6,8,10],
               'm6' : [1,3,5,7,9]}); 

# %%
df_pivot = df.pivot_table(index='index_date',columns=['portfolio','portfolio_ccy','reporting_ccy']).swaplevel(0, 1, axis=1).sortlevel(axis=1)
df1 = pd.DataFrame({'index_date' : ['12/07/2016','12/07/2016','12/07/2016','12/07/2016','12/07/2016'], 
           'portfolio' : ['A','B','C','D','E'], 
           'reporting_ccy' : ['JPY','USD','USD','EUR','EUR'],
           'portfolio_ccy' : ['JPY','USD','USD','EUR','EUR'],
           'amount' : [13767.2522, 263.34, 395.01, 474.785901, 593.4823763],
           'injection' : [1,2,3,4,5],
           'to_usd' : [0.009564, 1, 1, 1.1093, 1.1093],
           'to_ccy' : [1.3167, 1.3167, 1.3167, 1.3167, 1.3167],
           'm5' : [2,4,6,8,10],
           'm6' : [1,3,5,7,9]}); 

df_pivot.columns.names = ['portfolio','measures', 'portfolio_ccy', 'reporting_ccy']
# instead of joining the 2 df's add df1 to df_pivot 1 row at a time. 
for i in range(len(df1)):
    row = df1.iloc[i]
    for measure in 'amount injection m5 m6 to_ccy to_usd'.split():
        df_pivot.ix[row.index_date, (row.portfolio,measure,row.portfolio_ccy, row.reporting_ccy)] = row[measure]

#%% check the end result
print(df_pivot.xs(('amount', 'A'), 
      level=('measures','portfolio'), drop_level=False, axis=1))   

【讨论】:

  • 虽然您给出了与上述问题相同的答案,但您尚未回答该问题。问题是寻找一种更优化的方式将数据添加到多索引数据帧。请查看此link,我已在其中进一步探索。我不确定引入循环是否会比pd.concat 更优化。这是一个小例子,请在规模上考虑这一点,并跨度量进行计算以给出派生度量。
  • 在第一个枢轴上逐行追加可能比连接所有数据并在每次更新数据时重新计算所有枢轴在内存上的开销更低。因为您只需要处理新的传入数据,而不是一遍又一遍地处理现有数据。
  • 从深度多索引 df 转向 HDF5 或 SQL 可以进一步提高效率,但我认为这超出了问题的范围
【解决方案2】:

我对信息过载感到非常困惑。
但是,如果我理解正确:

我的意思是,没有一种简单的方法可以在多索引数据框中添加到较低级别。


考虑df

df = pd.DataFrame(np.arange(64).reshape(-1, 8), list('abcdefgh'), list('ABCDEFGH'))
df


我们可以很容易地为索引的内部层级添加一个层级

df.index = [df.index, list('XY') * 4]
df

【讨论】:

  • 您在上面的link 中提供了答案。这是 Pandas 核心开发人员应该帮助解决的问题。
  • 哈!我记性不好;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-18
  • 2017-02-06
相关资源
最近更新 更多