从具有值的组合创建矩阵

问题描述

我有一些组合,比如

(A,B) = 1
(A,C) = 0
(A,D) = 1
(B,C) = 1
(B,D) = 1
(C,D) = 0

关于如何使用来自所有这些组合的这些 0,1 值有效地创建四乘四矩阵的任何想法?所以结果将类似于:

  A B C D
A - 1 0 1
B 1 - 1 1
C 0 1 - 0
D 1 1 0 -

解决方法

想象一下,如果“组合”以以下格式(或类似格式)存储在文件中:

A,B,1
A,C,0
A,D,1
B,1
C,0

然后你可以这样做:

df = pd.read_csv(filename,header=None)

示例(使用您的示例数据):

txt = """A,0
"""
df = pd.read_csv(io.StringIO(txt),header=None)

现在 df 包含:

   0  1  2
0  A  B  1
1  A  C  0
2  A  D  1
3  B  C  1
4  B  D  1
5  C  D  0

从那时起,一点点按摩就会得到你想要的:

# all labels (for rows and cols)
r = sorted(set(df[0]) | set(df[1]))

# upper triangular
z = (
    df.set_index([0,1])
    .reindex(pd.MultiIndex.from_product([r,r]))
    .squeeze()
    .unstack(1)
)

# fill in the lower triangular part to make z symmetric
z = z.where(~z.isna(),z.T)

我们得到:

>>> z
     A    B    C    D
A  NaN  1.0  0.0  1.0
B  1.0  NaN  1.0  1.0
C  0.0  1.0  NaN  0.0
D  1.0  1.0  0.0  NaN

注意:如果您更喜欢保持在 int-only(并将对角线设置为 0),则:

z = (
    df.set_index([0,r]),fill_value=0)
    .squeeze()
    .unstack(1)
)
z += z.T

现在:

>>> z
   A  B  C  D
A  0  1  0  1
B  1  0  1  1
C  0  1  0  0
D  1  1  0  0

为了速度

现在,如果您确定要处理 4x4 矩阵并且顺序与您所指示的完全相同(按上面的三角形排序),您可以执行以下操作以加快设置速度:

# get the triangular values,somehow (e.g. read file and discard
# all but the last value;

# here we simply take them from the df above:
tri = df[2].values  # np.array([1,1,0])

# and now,in pure numpy:
z = np.zeros((4,4),dtype=int)
z[np.triu_indices(4,1)] = tri
z += z.T

结果是一个简单的 numpy 数组(无标签):

>>> z
[[0 1 0 1]
 [1 0 1 1]
 [0 1 0 0]
 [1 1 0 0]]
,

您可以通过枢轴操作轻松完成。假设您的组合出现在一个看起来像这样的 csv 文件中(它们可以很容易地出现在某些数据结构中,例如字典或 2D​​ 列表):

A,A
B,B
C,C
D,D

然后你可以这样做:

df = pd.read_csv('sample.csv',header=None)
df.columns = ['col1','col2','value']

df = df.pivot(index='col1',columns='col2',values='value')
df =df.where(~df.isna(),df.T) #reflects half-matrix across diagonal
df.fillna('-',inplace=True)

print(df)

#output:
col2  A  B  C  D
col1            
A     -  1  0  1
B     1  -  1  1
C     0  1  -  0
D     1  1  0  -