Pandas:将操作应用于多索引中的重复列

2023-12-29

我有 MultiColumns:第二级重复包含Job Openings and Hires。我想为每个顶级列减去一个,但我所做的一切都会让我陷入索引错误或切片错误。我怎样才能计算它?

样本数据:

>>> df.head()
Out[25]: 
           Total nonfarm              Total private               
                   Hires Job openings         Hires Job openings   
date                                                               
2001-01-01          5777         5385          5419         4887   
2002-01-01          4849         3759          4539         3381   
2003-01-01          4971         3824          4645         3424   
2004-01-01          4827         3459          4552         3153   
2005-01-01          5207         3670          4876         3358  

预期输出:

Out[25]: 
           Total nonfarm   Total private              
              difference      difference   
date                                                               
2001-01-01          1234            5678          
2002-01-01          1234            5678          
2003-01-01          1234            5678         
2004-01-01          1234            5678      
2005-01-01          1234            5678    

其中数字显然不正确。

特别是在 apply() 中

为了有一个普遍适用的方式,我试图建立

def apply(group):
    result = group.loc[:, pd.IndexSlice[:, 'Job openings']].div(group.loc[:, pd.IndexSlice[:, 'Hires']].values)
    result.columns = pd.MultiIndex.from_product([[group.columns.get_level_values(0)[0]], ['Ratio']])
    return result.values
foo = df.groupby(axis=1, level=0).apply(apply)

它存在两个问题:

  • 我需要欺骗.values为了得到正确的划分
  • foo不是一个正确的数据框:

    住宿和餐饮服务 [[0.76]、[0.480349344978]、[0.501388888889]、[... 艺术、娱乐和休闲 [[0.558139534884]、[0.46017699115]、[0.2483221... 建设 [[0.35], [0.274881516588], [0.267260579065], [...

我首先尝试返回result, 代替result.values,但这只会导致一个充满了的数据框NaN

特别是使用列名

我不喜欢得票最高的答案是它需要.diff() or .div()- 黑客行为,使得代码难以阅读,并且当子级别有两列以上时难以实现。


Setup

import pandas as pd

df = pd.DataFrame(
    [
        [5777, 5385, 5419, 4887],
        [4849, 3759, 4539, 3381],
        [4971, 3824, 4645, 3424],
        [4827, 3459, 4552, 3153],
        [5207, 3670, 4876, 3358],
    ],
    index=pd.to_datetime(['2001-01-01',
                          '2002-01-01',
                          '2003-01-01',
                          '2004-01-01',
                          '2005-01-01']),
    columns=pd.MultiIndex.from_tuples(
        [('Total nonfarm', 'Hires'), ('Total nonfarm', 'Job Openings'),
         ('Total private', 'Hires'), ('Total private', 'Job Openings')]
    )
)

print df

           Total nonfarm              Total private             
                   Hires Job Openings         Hires Job Openings
2001-01-01          5777         5385          5419         4887
2002-01-01          4849         3759          4539         3381
2003-01-01          4971         3824          4645         3424
2004-01-01          4827         3459          4552         3153
2005-01-01          5207         3670          4876         3358

Try:

df.T.groupby(level=0).diff(-1).dropna().T

           Total nonfarm Total private
                   Hires         Hires
2001-01-01         392.0         532.0
2002-01-01        1090.0        1158.0
2003-01-01        1147.0        1221.0
2004-01-01        1368.0        1399.0
2005-01-01        1537.0        1518.0

要应用其他变换(例如比率),您可以执行以下操作:

print df.T.groupby(level=0).apply(lambda x: np.exp(np.log(x).diff(-1))).dropna().T

           Total nonfarm Total private
                   Hires         Hires
2001-01-01      1.072795      1.108860
2002-01-01      1.289971      1.342502
2003-01-01      1.299948      1.356600
2004-01-01      1.395490      1.443704
2005-01-01      1.418801      1.452055

Or:

print df.T.groupby(level=0).apply(lambda x: x.div(x.shift(-1))).dropna().T

           Total nonfarm Total private
                   Hires         Hires
2001-01-01      1.072795      1.108860
2002-01-01      1.289971      1.342502
2003-01-01      1.299948      1.356600
2004-01-01      1.395490      1.443704
2005-01-01      1.418801      1.452055

要重命名列并与原始数据框合并,您可以:

df2 = df.T.groupby(level=0).diff(-1).dropna().T
df2.columns = pd.MultiIndex.from_tuples(
    [('Total nonfarm', 'difference'),
     ('Total private', 'difference')])
pd.concat([df, df2], axis=1).sort_index(axis=1)

好像:

           Total nonfarm                         Total private               \
                   Hires Job Openings difference         Hires Job Openings   
2001-01-01          5777         5385      392.0          5419         4887   
2002-01-01          4849         3759     1090.0          4539         3381   
2003-01-01          4971         3824     1147.0          4645         3424   
2004-01-01          4827         3459     1368.0          4552         3153   
2005-01-01          5207         3670     1537.0          4876         3358   

           difference  
2001-01-01      532.0  
2002-01-01     1158.0  
2003-01-01     1221.0  
2004-01-01     1399.0  
2005-01-01     1518.0  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Pandas:将操作应用于多索引中的重复列 的相关文章