我有一个带有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倍。
答案 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