如何用python中的条件进行矩阵乘法?

How to perform Matrix multiplication with conditions in python?

我在数据帧上使用矩阵乘法并将其转置 df@df.T

所以如果我有一个 df 看起来像:(低于 1 表示对象有 属性 而 0 表示没有):

Object Property1 Property2 Property3
A      1         1         1
B      0         1         1
C      1         0         0

使用 df@df.T 给我:

   A  B  C
A  3  2  1  
B  2  2  0
C  1  0  1

这可以被认为是一个矩阵,显示每个对象与另一个对象共有多少属性。

我现在想修改问题,而不是二进制指示对象是否具有 属性,属性列显示 属性 的级别。所以新的 df 看起来像:(属性值 1、2、3 下方显示其级别。但 0 表示没有 属性)

Object Property1 Property2 Property3
A      3         2         1
B      0         2         3
C      2         0         0

我想应用矩阵乘法,但更改了 'common' 属性的定义。如果 属性 的级别在另一个 属性.

的 +-1 范围内,则两个对象将只有一个共同的 属性

结果如下所示:

   A  B  C
A  3  1  1  
B  1  2  0
C  1  0  1

注意A和B共有的属性个数从2变成了1。这是因为属性A和B之间的3个不在+-1级之内。此外,0 仍然意味着该对象没有 属性,因此 A 和 C 仍然有 1 个 属性(C 的 属性 3 为 0)。

如何在 Python 中实现此目的?

这可以通过修改两个数据帧的矩阵乘法来完成

代码

# DataFrame Matrix Multiplication
# i.e. equivalent to df1@df2
def df_multiply(df_a, df_b):
  '''
     Matrix multiplication of values in two DataFrames
     Returns a DataFrame whose index and column are
     from the df_a 
  '''
  a = df_a.values
  b = df_b.values
  zip_b = zip(*b)
  zip_b = list(zip_b)
  zip_b = b
  result = [[sum(ele_a*ele_b for ele_a, ele_b in zip(row_a, col_b)) 
             for col_b in zip_b] for row_a in a]

  return pd.DataFrame(data=result, index=df_a.index, columns=df_a.index)

# Modify df_multiply for desired result
def df_multiply_modified(df_a, df_b):
  '''
         Modified Matrix multiplication of values in two DataFrames to create desired result
         Returns a DataFrame whose index and
         column are from the df_a
  '''
  a = df_a.values
  b = df_b.values
  zip_b = zip(*b)
  zip_b = list(zip_b)
  
  # sum 1 when difference <= 1 and 
  # values are non-zero
  # i.e. ele_a and ele_b and abs(ele_a-ele_b) <=1
  result = [[sum(1 if ele_a and ele_b and abs(ele_a-ele_b) <=1 else 0 for ele_a, ele_b in zip(row_a, col_b)) 
             for col_b in zip_b] for row_a in a]

  return pd.DataFrame(data=result, index=df_a.index, columns=df_a.index)

用法

原乘法

df = pd.DataFrame({'Object':['A', 'B', 'C'],
                  'Property1':[1, 0, 1],
                  'Property2':[1, 1, 0],
                  'Property3':[1, 1, 0]})

df.set_index('Object', inplace = True)
print(df_multiply(df, df.T)
# Output (same as df@df.T):
Object  A  B  C
Object         
A       3  2  1
B       2  2  0
C       1  0  1 

修正乘法

# Use df_multiply_modified
df = pd.DataFrame({'Object':['A', 'B', 'C'],
                  'Property1':[3, 0, 2],
                  'Property2':[2, 2, 0],
                  'Property3':[1, 3, 0]})
df.set_index('Object', inplace = True)
print(df_multiply_modified(df, df.T)
# Output (same as desired)
Object  A  B  C
Object         
A       3  1  1
B       1  2  0
C       1  0  1