Python 将NumPy矩阵不同值部分的上下三角提取到2列
我有一个Python 将NumPy矩阵不同值部分的上下三角提取到2列,python,pandas,dataframe,numpy,Python,Pandas,Dataframe,Numpy,我有一个测试矩阵: A B C A nan 10 20 B 30 nan 40 C 50 60 nan 我的数据帧应该是: cus1 cus2 lower upper A B 30 10 A C 50 20 B C 60 40 cus1 cus2 lower upper A B 40 10
测试矩阵
:
A B C
A nan 10 20
B 30 nan 40
C 50 60 nan
我的数据帧应该是:
cus1 cus2 lower upper
A B 30 10
A C 50 20
B C 60 40
cus1 cus2 lower upper
A B 40 10
A C 70 20
A D 100 30
B C 80 50
B D 110 60
D C 120 90
我可以用两部分提取上面的数据帧(我首先提取上面的三角形,然后提取下面的三角形):
但是当我创建一个数据帧时,我有一堆代码,要提取上面正确的数据帧非常复杂
我能提取一次吗
更新解决方案
Mr/Ms Pygirl给出了一个很好的解决方案,但当矩阵值0
时:
A B C
A nan 10 0
B 30 nan 40
C 0 60 nan
Pygirl解决方案将给出一个结果:
cus1 cus2 lower upper
A B 30 10
B C 60 40
如果要获取值0
(索引:AC
和CA
),应使用:
df2=df.where(np.triu(np.ones(df.shape)).astype(np.bool)).stack().rename_axis(('cus1', 'cus2')).reset_index(name='upper')
y=df.where(np.tril(np.ones(df.shape)).astype(np.bool)).stack().values
结果是:
cus1 cus2 lower upper
A B 30 10
A C 0 0
B C 60 40
问题2(使用PYGIRL-SOLUTION后)
我有一个4x4维的测试矩阵
:
A B C D
A nan 10 20 30
B 40 nan 50 60
C 70 80 nan 90
D 100 110 120 nan
我的数据帧应该是:
cus1 cus2 lower upper
A B 30 10
A C 50 20
B C 60 40
cus1 cus2 lower upper
A B 40 10
A C 70 20
A D 100 30
B C 80 50
B D 110 60
D C 120 90
但是我得到了一个错误的结果(失去了DC和错误的AD,BC):
尝试:
df2:
cus1 cus2 upper lower
0 A B 10.0 30.0
1 A C 20.0 50.0
2 B C 40.0 60.0
cus2 cus1 lower upper
0 B A 40.0 10.0
1 C A 70.0 20.0
2 C B 80.0 50.0
3 D A 100.0 30.0
4 D B 110.0 60.0
5 D C 120.0 90.0
编辑: df3:
cus1 cus2 upper lower
0 A B 10.0 30.0
1 A C 20.0 50.0
2 B C 40.0 60.0
cus2 cus1 lower upper
0 B A 40.0 10.0
1 C A 70.0 20.0
2 C B 80.0 50.0
3 D A 100.0 30.0
4 D B 110.0 60.0
5 D C 120.0 90.0
代码设置:
import pandas as pd
import numpy as np
test_matrix = np.array([[np.nan,10,20],[30,np.nan,40],[50,60,np.nan]])
lower_triangular = test_matrix[np.tril_indices(test_matrix.shape[0], -1)]
lower_triangular = list(np.tril(test_matrix).flat)
upper_triangular = list(np.triu(test_matrix).flat)
lower_triangular = [x for x in lower_triangular if x>0]
upper_triangular = [x for x in upper_triangular if x>0]
cus1 = np.tril_indices(test_matrix.shape[0], -1)[0]
cus2 = np.tril_indices(test_matrix.shape[0], -1)[1]
q = pd.DataFrame(
{'cus1': cus1,
'cus2': cus2,
'lower': lower_triangular,
'upper': upper_triangular
})
输出:
cus1 cus2 lower upper
0 1 0 30.0 10.0
1 2 0 50.0 20.0
2 2 1 60.0 40.0
你能展示你的解决方案吗?我假设您已经使用了
np.triu
和np.tril
。嗨@MichaelSzczesny,我更新了代码。当然,你也可以提供你用来创建测试矩阵的代码吗?嗨@srishtigarg,这是我的代码a=np.array([[np.nan,10,20],[30,np.nan,40],[50,60,np.nan]])
你帮了我很大的忙,@Pygirl。你的解决方案让我更有见识。非常感谢你。非常感谢,但我能问你一个问题吗?为什么我们需要astype(np.bool)
.df.where-->替换条件为False的值。df.where
将设置值0
,而nAn
为False,我是否可以保留值0
?当进行堆栈时,您将看到差异。试着部分地运行代码。由于我需要取上面的对角线值,所以我将使用df将其余部分作为nan。其中
我的对角线值也将在那里,但幸运的是它们都是nan(最初),所以我不必在进行堆栈之前将它们转换为nan。希望你明白我的意思