Python,熊猫:如何从对称的多索引数据帧中提取值

Python,熊猫:如何从对称的多索引数据帧中提取值,python,pandas,numpy,dataframe,multi-index,Python,Pandas,Numpy,Dataframe,Multi Index,我有一个对称的多索引数据框,我想从中系统地提取数据: import pandas as pd df_index = pd.MultiIndex.from_arrays( [["A", "A", "B", "B"], [1, 2, 3, 4]], names = ["group", "id"]) df = pd.DataFrame( [[1.0, 0.5, 0.3, -0.4], [0.5, 1.0, 0.9, -0.8], [0.3, 0.9, 1.0, 0

我有一个对称的多索引数据框,我想从中系统地提取数据:

import pandas as pd

df_index = pd.MultiIndex.from_arrays(
    [["A", "A", "B", "B"], [1, 2, 3, 4]], names = ["group", "id"])
df = pd.DataFrame(
    [[1.0, 0.5, 0.3, -0.4],
     [0.5, 1.0, 0.9, -0.8],
     [0.3, 0.9, 1.0, 0.1],
     [-0.4, -0.8, 0.1, 1.0]],
    index=df_index, columns=df_index)
我需要一个函数
extract\u vals
,该函数可以返回与同一组中的元素相关的所有值,对角线除外,元素不能重复计数。以下是所需行为的两个示例(顺序无关紧要):

我的问题与类似,但我的情况不同,因为我使用的是多索引数据帧

最后,为了让事情更有趣,请考虑效率,因为我将在更大的数据流上运行很多次。非常感谢

编辑: Happy001的解决方案非常棒。我自己提出了一种基于逻辑的方法,提取target不在行和列中的元素,然后提取target同时在行和列中的元素的下三角。然而,Happy001的解决方案要快得多

首先,我创建了一个更复杂的数据框架,以确保两种方法都是通用的:

import pandas as pd
import numpy as np

df_index = pd.MultiIndex.from_arrays(
    [["A", "B", "A", "B", "C", "C"], [1, 2, 3, 4, 5, 6]], names=["group", "id"])
df = pd.DataFrame(
    [[1.0, 0.5, 1.0, -0.4, 1.1, -0.6],
     [0.5, 1.0, 1.2, -0.8, -0.9, 0.4],
     [1.0, 1.2, 1.0, 0.1, 0.3, 1.3],
     [-0.4, -0.8, 0.1, 1.0, 0.5, -0.2],
     [1.1, -0.9, 0.3, 0.5, 1.0, 0.7],
     [-0.6, 0.4, 1.3, -0.2, 0.7, 1.0]],
    index=df_index, columns=df_index)
接下来,我定义了extract_vals的两个版本(第一个版本是我自己的):

最后,我检查了速度:

## Test speed
import time

# Method 1
start1 = time.time()
for ii in range(10000):
    out = extract_vals("C", "group", df)
elapsed1 = time.time() - start1
print elapsed1 # 28.5 sec

# Method 2
start2 = time.time()
for ii in range(10000):
    out2 = extract_vals2("C", "group", df)
elapsed2 = time.time() - start2
print elapsed2 # 10.9 sec
这就是你想要的吗

对角线上方的所有元素:

In [139]: df.values[np.triu_indices(len(df), 1)]
Out[139]: array([ 0.5,  0.3, -0.4,  0.9, -0.8,  0.1])
A_vals:

In [140]: df.values[np.triu_indices(len(df), 1)][:-1]
Out[140]: array([ 0.5,  0.3, -0.4,  0.9, -0.8])
B_vals:

In [141]: df.values[np.triu_indices(len(df), 1)][1:]
Out[141]: array([ 0.3, -0.4,  0.9, -0.8,  0.1])
源矩阵:

In [142]: df.values
Out[142]:
array([[ 1. ,  0.5,  0.3, -0.4],
       [ 0.5,  1. ,  0.9, -0.8],
       [ 0.3,  0.9,  1. ,  0.1],
       [-0.4, -0.8,  0.1,  1. ]])

我不认为
df
具有相同的列和索引。(当然,它们可以是相同的)


这不是一个通用函数,因为您必须在tril和triu之间切换,对吗?此外,使用此实现,如果我想要保留的数据点之一为0,我将丢失它。我不知道你可以使用点符号访问数据;这很好。
.values
提供了
pandas
数据帧后面使用的
numpy
数组。你能展示一下你尝试过的吗?我在最近的编辑中包含了我的解决方案。希望能有帮助,梅林。
In [140]: df.values[np.triu_indices(len(df), 1)][:-1]
Out[140]: array([ 0.5,  0.3, -0.4,  0.9, -0.8])
In [141]: df.values[np.triu_indices(len(df), 1)][1:]
Out[141]: array([ 0.3, -0.4,  0.9, -0.8,  0.1])
In [142]: df.values
Out[142]:
array([[ 1. ,  0.5,  0.3, -0.4],
       [ 0.5,  1. ,  0.9, -0.8],
       [ 0.3,  0.9,  1. ,  0.1],
       [-0.4, -0.8,  0.1,  1. ]])
def extract_vals(group_label, df):    
    coord = [[i, j] for i in range(len(df)) for j in range(len(df)) if i<j and (df.index.get_level_values('group')[i] == group_label or df.columns.get_level_values('group')[j] == group_label) ]
    return df.values[tuple(np.transpose(coord))]

print extract_vals('A', df)
print extract_vals('B', df)
[ 0.5  0.3 -0.4  0.9 -0.8]
[ 0.3 -0.4  0.9 -0.8  0.1]