【问题标题】:create a matrix from combinations with values从具有值的组合创建矩阵
【发布时间】:2023-04-08 16:57:02
【问题描述】:

我有一些组合,比如

(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 -

【问题讨论】:

  • 你的矩阵的对角线是零吗?另外,您尝试过什么,您是否有可行的解决方案并且只是在寻找更快的方法?如果有,请附上。
  • 这些组合是如何存储的?
  • 是的,对角线可以为零!我想不出任何可行的解决方案!
  • 组合存储在文本文件中。
  • 请注意,python 中的矩阵以其最简单的形式可以被认为是列表的列表。这里,它是一个包含 4 个长度为 4 的列表的列表:这 4 个列表中的每一个都是一行。您还可以看到一些实际矩阵结构的 numpy,这可以帮助您更快地构建它。

标签: python numpy matrix numpy-ndarray


【解决方案1】:

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

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

那么你可以这样做:

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

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

txt = """A,B,1
A,C,0
A,D,1
B,C,1
B,D,1
C,D,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, 1])
    .reindex(pd.MultiIndex.from_product([r, 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, 0, 1, 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]]

【讨论】:

    【解决方案2】:

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

    A,B,1
    A,C,0
    A,D,1
    B,C,1
    B,D,1
    C,D,0
    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  -
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-21
      • 2019-05-22
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      • 2021-09-22
      • 1970-01-01
      • 2020-09-19
      相关资源
      最近更新 更多