问题描述
我有一些组合,比如
(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 -