Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pandas 多索引isn';当pd包含多个小计行时保留t_Pandas_Multi Index - Fatal编程技术网

Pandas 多索引isn';当pd包含多个小计行时保留t

Pandas 多索引isn';当pd包含多个小计行时保留t,pandas,multi-index,Pandas,Multi Index,当我试图进行第二次小计时,我失去了多重索引。我可以添加第一个小计,但不能添加第二个小计,即B0的总和 这就是我当前的df: lvl0 a b lvl1 bar foo bah foo A0 B0 C0 D0 1 0 3 2 D1 5 4 7 6 First Total

当我试图进行第二次小计时,我失去了多重索引。我可以添加第一个小计,但不能添加第二个小计,即B0的总和

这就是我当前的df:

lvl0                    a         b     
lvl1                  bar  foo  bah  foo
A0 B0 C0 D0             1    0    3    2
         D1             5    4    7    6
         First Total    6    4   10    8
      C1 D0             9    8   11   10
         D1            13   12   15   14
         First Total   22   20   26   24
      C2 D0            17   16   19   18
尝试添加第二个小计后,我得到以下结果:

lvl0                            a           b      
lvl1                          bar   foo   bah   foo
(A0, B0, C2, First Total)    38    36    42    40
(A0, B0, C3, D0)             25    24    27    26
(A0, B0, C3, D1)             29    28    31    30
(A0, B0, C3, First Total)    54    52    58    56
(A0, B0, Second Total)      120   112   136   128
(A0, B1, C0, D0)             33    32    35    34
(A0, B1, C0, D1)             37    36    39    38
(A0, B1, C0, First Total)    70    68    74    72
(A0, B1, C1, D0)             41    40    43    42

您应该能够复制并粘贴下面的代码以进行测试

import pandas as pd
import numpy as np

# creating multiIndex
def mklbl(prefix, n):
    return ["%s%s" % (prefix, i) for i in range(n)]


miindex = pd.MultiIndex.from_product([mklbl('A', 4),
                                        mklbl('B', 2),
                                        mklbl('C', 4),
                                        mklbl('D', 2)])


micolumns = pd.MultiIndex.from_tuples([('a', 'foo'), ('a', 'bar'),
                                        ('b', 'foo'), ('b', 'bah')],
                                      names=['lvl0', 'lvl1'])


dfmi = pd.DataFrame(np.arange(len(miindex) * len(micolumns))
                     .reshape((len(miindex), len(micolumns))),
                    index=miindex,
                   columns=micolumns).sort_index().sort_index(axis=1)

# My code STARTS HERE
# creating the first subtotal
print(dfmi.index)
df1 = dfmi.groupby(level=[0,1,2]).sum()
df2 = dfmi.groupby(level=[0, 1]).sum()

df1 = df1.set_index(np.array(['First Total'] * len(df1)), append=True)
dfmi = pd.concat([dfmi, df1]).sort_index(level=[0, 1])

print(dfmi)

# this is where the multiIndex is lost
df2 = df2.set_index(np.array(['Second Total'] * len(df2)), append=True)
dfmi = pd.concat([dfmi, df2]).sort_index(level=[1])

print(dfmi)

我希望它看起来怎么样:

lvl0                    a         b     
lvl1                  bar  foo  bah  foo
A0 B0 C0 D0             1    0    3    2
         D1             5    4    7    6
         First Total    6    4   10    8
      C1 D0             9    8   11   10
         D1            13   12   15   14
         First Total   22   20   26   24
      C2 D0            17   16   19   18
         D1            21   20   23   22
         First Total   38   36   42   40
      C3 D0            25   24   27   26
         D1            29   28   31   30
         First Total   54   52   58   56
      Second Total     120  112  136  128
   B1 C0 D0            33   32   35   34
         D1            37   36   39   38
         First Total   70   68   74   72
      C1 D0            41   40   43   42
         D1            45   44   47   46
         First Total   86   84   90   88
      C2 D0            49   48   51   50
         D1            53   52   55   54
         First Total  102  100  106  104
      C3 D0            57   56   59   58
         D1            61   60   63   62
         First Total  118  116  122  120
       Second Total   376  368  392  384
第一个总数是第二级的总和,
第二个总数是1级dfmi的总和,dfmi有一个4级多索引:

In [208]: dfmi.index.nlevels
Out[208]: 4
df2
具有三级多索引。相反,如果您使用

df2 = df2.set_index([np.array(['Second Total'] * len(df2)), [''] * len(df2)], append=True)
然后,
df2
以4级多索引结束。当
dfmi
df2
具有相同的级别数时, 然后
pd.concat([dfmi,df2])
生成所需的结果


按索引标签排序时可能遇到的一个问题是,它依赖于字符串
'First'
'Second'
按字母顺序排在最后的。按索引排序的替代方法是指定一个数值
顺序
列
而按此排序:

dfmi['order'] = range(len(dfmi))
df1['order'] = dfmi.groupby(level=[0,1,2])['order'].last() + 0.1
df2['order'] = dfmi.groupby(level=[0,1])['order'].last() + 0.2
...
dfmi = pd.concat([dfmi, df1, df2])        
dfmi = dfmi.sort_values(by='order')

合并后,代码将如下所示:

import pandas as pd
import numpy as np

def mklbl(prefix, n):
    return ["%s%s" % (prefix, i) for i in range(n)]


miindex = pd.MultiIndex.from_product([mklbl('A', 4),
                                        mklbl('B', 2),
                                        mklbl('C', 4),
                                        mklbl('Z', 2)])


micolumns = pd.MultiIndex.from_tuples([('a', 'foo'), ('a', 'bar'),
                                        ('b', 'foo'), ('b', 'bah')],
                                      names=['lvl0', 'lvl1'])


dfmi = pd.DataFrame(np.arange(len(miindex) * len(micolumns))
                     .reshape((len(miindex), len(micolumns))),
                    index=miindex,
                   columns=micolumns).sort_index().sort_index(axis=1)

df1 = dfmi.groupby(level=[0,1,2]).sum()
df2 = dfmi.groupby(level=[0, 1]).sum()

dfmi['order'] = range(len(dfmi))
df1['order'] = dfmi.groupby(level=[0,1,2])['order'].last() + 0.1
df2['order'] = dfmi.groupby(level=[0,1])['order'].last() + 0.2

df1 = df1.assign(lev4='First').set_index('lev4', append=True)
df2 = df2.assign(lev3='Second', lev4='').set_index(['lev3','lev4'], append=True)
dfmi = pd.concat([dfmi, df1, df2])
dfmi = dfmi.sort_values(by='order')
dfmi = dfmi.drop(['order'], axis=1)
print(dfmi)
产生

lvl0                  a         b     
lvl1                bar  foo  bah  foo
A0 B0 C0     Z0       1    0    3    2
             Z1       5    4    7    6
             First    6    4   10    8
      C1     Z0       9    8   11   10
             Z1      13   12   15   14
             First   22   20   26   24
      C2     Z0      17   16   19   18
             Z1      21   20   23   22
             First   38   36   42   40
      C3     Z0      25   24   27   26
             Z1      29   28   31   30
             First   54   52   58   56
      Second        120  112  136  128
...

@联合国大学指出了问题的本质。df2有三个级别的多索引,您需要第四个级别

我将使用
assign
set\u index
创建第四级:

df2 = df2.assign(lev3='Second Total', lev4='').set_index(['lev3','lev4'], append=True)
这样可以避免计算数据帧的长度