在多索引中访问对角线

时间:2015-10-12 15:20:01

标签: pandas

我有一个带有rank-3多索引的pandas DataFrame。我想提取"对角线"在前两个指数中。即提取前两个索引彼此相等的值,而第三个索引获取所有可能的值。

以下是生成此类DataFrame的示例代码。

    Ext.Ajax.request({
            url: projectparameters.service + 'importxxxxx.php',
            scope: this,
            method: "POST",
            params: {
                projectparameters: JSON.stringify(projectparameters),
                ftpUrl: ftpUrl,
                fileName: fileName,
                fileDate: fileDate
            },
            success: function(response, rowIndex){

                var feedback = JSON.parse(response.responseText);
                if(feedback.success === false) {
                    Ext.Msg.alert('Error', feedback.msg);
                }
                else if( feedback.success === true ) {
                    Ext.Msg.alert('Success', feedback.msg);
                    // After uploading the file - reload import-history
                    var importHistoryTab = Ext.getCmp('grid_ImportHistory');
                    importHistoryTab.getStore().reload();
                    var featureGrid = Ext.getCmp("featuregrid");
                    featureGrid.getStore().reload();
                }
            },
            failure: function(response, rowIndex){
                console.log('response: ');
                console.log(response);

                Ext.Msg.alert('Error', 'File could not be imported - '+response.statusText+'.<br> Aborted: '+response.isAbort+'. <br>Timeout: '+response.isTimeout+'.');
            }
    });

DataFrame看起来像这样:

import pandas as pd
import numpy as np

df = pd.DataFrame()

d = 0
e = 1
for A in xrange(3):
    for B in xrange(3):
        for C in xrange(2):
            df = df.append(dict(A=A, B=B, C=C, d=d, e=e), ignore_index=True)
            d += 2
            e += 2

df.set_index(['A', 'B', 'C'], inplace=True)
df.sortlevel(inplace=True)
print df

我想提取 d e A B C 0 0 0 0 1 1 2 3 1 0 4 5 1 6 7 2 0 8 9 1 10 11 1 0 0 12 13 1 14 15 1 0 16 17 1 18 19 2 0 20 21 1 22 23 2 0 0 24 25 1 26 27 1 0 28 29 1 30 31 2 0 32 33 1 34 35 A相等的行(以有效的方式,因为真正的DataFrame有{1}}的100-1000个值,{{{ 1}})。鉴于上面的示例,我想提取以下DataFrame:

B

我已尝试使用以下代码。

A

打印:

B

如您所见,它只是选择所有数据。

我的问题是,如何从DataFrame(如上面给出的那个)中有效地提取 d e A B C 0 0 0 0 1 1 2 3 1 1 0 16 17 1 18 19 2 2 0 32 33 1 34 35 ind = np.diag_indices(3) + (slice(None),) df_diag = df.loc[ind, slice(None)] print df_diag 具有相同值的行。

编辑:答案基准

使用以下代码生成更大的数据帧:

        d   e
A B C
0 0 0   0   1
    1   2   3
  1 0   4   5
    1   6   7
  2 0   8   9
    1  10  11
1 0 0  12  13
    1  14  15
  1 0  16  17
    1  18  19
  2 0  20  21
    1  22  23
2 0 0  24  25
    1  26  27
  1 0  28  29
    1  30  31
  2 0  32  33
    1  34  35

我测试了@ Alexander的回答:

A

导致:

B

我测试了@ Fabio的回答:

numAB = 100
numC = 10
num = numAB**2 * numC
A = np.repeat(np.arange(numAB), numAB * numC)
B = np.tile(np.repeat(np.arange(numAB), numC), numAB)
C = np.tile(np.arange(numC), numAB**2)
d = np.arange(num) * 2
e = d + 1
dflarge = pd.DataFrame(dict(A=A, B=B, C=C, d=d, e=e)).set_index(['A', 'B', 'C'])

导致:

%%timeit
res = pd.concat([dflarge.loc[pd.IndexSlice[n, n, :], :] for n in dflarge.index.levels[0]])

后者的速度提高了约10倍。

2 个答案:

答案 0 :(得分:1)

我首先用:

重置数据帧的索引
df = df.reset_index()

然后选择过滤器来选择你想要的东西:

d = df[df['A']==df['B']]

最后再次设置索引:

d.set_index(['A', 'B', 'C'], inplace=True)

返回:

        d   e
A B C        
0 0 0   0   1
    1   2   3
1 1 0  16  17
    1  18  19
2 2 0  32  33
    1  34  35

答案 1 :(得分:1)

鉴于索引的第一级和第二级相同,您可以使用IndexSlice使用第一级的内容。

>>> pd.concat([df.loc[pd.IndexSlice[n, n, :], :] for n in df.index.levels[0]])
Out[278]: 
        d   e
A B C        
0 0 0   0   1
    1   2   3
1 1 0  16  17
    1  18  19
2 2 0  32  33
    1  34  35