计算矩阵行的加权平均,但每行的权重不同?

huangapple go评论70阅读模式
英文:

How to calculate the weighted average of the rows of a matrix, but with different weights per row?

问题

根据您的请求,以下是翻译好的代码部分:

# 生成矩阵和权重数组
mat = np.array([[       0,     2436,     2434,     2428,     2416],
                [    2436,        0,     2454,     2446,     2435],
                [    2434,     2454,        0,     2447,     2436],
                [    2428,     2446,     2447,        0,     2428],
                [    2416,     2435,     2436,     2428,        0]])
weights = np.array([262140,   196608,   196608, 196608, 196608])

# 当前(错误)实现:
# 计算加权平均值
weighted_avg = np.average(mat, axis=-1, weights=weights)
print(weighted_avg)

# 循环实现:
weighted_avg = []
for i in range(mat.shape[0]):
    curr_weights = weights.copy()
    curr_weights[i] = 0
    weighted_avg.append(np.average(mat[i], axis=-1, weights=curr_weights))

weighted_avg = np.array(weighted_avg)
print(weighted_avg)

请注意,以上是代码的翻译,没有其他内容。

英文:

As the title implies, I have a numpy matrix (2d array) that happens to be symmetric with 0s in its diagonal.
I wanted to use the np.average method in order to collapse its rows into a 1d column array of weighted averages using a weight array from the same length of the rows of the matrix.
However, since the diagonals are zeros for a justified reason, I don't want to count it in the result of the row's weighted average.
In other words, I want a varying set of weights for each row, such that for the row i the corresponding weight[i] will be zero and the rest of the weights will remain the same.

Is it possible to do this without an explicit loop?
What is the best way to do it?

Code example-
Generate the matrix and the weights:

mat = np.array([[       0,     2436,     2434,     2428,     2416],
                [    2436,        0,     2454,     2446,     2435],
                [    2434,     2454,        0,     2447,     2436],
                [    2428,     2446,     2447,        0,     2428],
                [    2416,     2435,     2436,     2428,        0]])
weights = np.array([262140,   196608,   196608, 196608, 196608])

Current (wrong) implementation:
Calculate the weighted average:

weighted_avg = np.average(mat, axis=-1, weights=weights)
print(weighted_avg)

Out: [1821.38194802 1984.31077694 1984.18578409 1979.68578982 1972.56080841]

Loop implementation:

weighted_avg = []
for i in range(mat.shape[0]):
    curr_weights = weights.copy()
    curr_weights[i] = 0
    weighted_avg.append(np.average(mat[i], axis=-1, weights=curr_weights))

weighted_avg = np.array(weighted_avg)
print(weighted_avg)

Out: [2428.5        2442.23079848 2442.076961   2436.53850163 2427.76928603]

How can I make this loop implementation work using 'proper numpy'?

答案1

得分: 1

创建一个形状为(mat.shape[0],mat.shape[1])的矩阵,其中每一行都是weights的副本

all_weights = np.tile(weights, (mat.shape[0], 1))

将对角线元素设为零

np.fill_diagonal(all_weights, 0)

使用all_weights沿着最后一个轴(-1)计算加权平均值

weighted_avg = np.average(mat, axis=-1, weights=all_weights)
print(weighted_avg)

输出:[2428.5 2442.23079848 2442.076961 2436.53850163 2427.76928603]

英文:

I think I found a solution to this question. Would be great if someone could approve but it seems to work:

# Create a matrix of shape (mat.shape[0], mat.shape[1]) where each row is a copy of `weights`
all_weights = np.tile(weights, (mat.shape[0], 1))

# Set the diagonal elements to zero
np.fill_diagonal(all_weights, 0)

# Calculate the weighted average along the last axis (-1) using `all_weights`
weighted_avg = np.average(mat, axis=-1, weights=all_weights)
print(weighted_avg)

Out: [2428.5        2442.23079848 2442.076961   2436.53850163 2427.76928603]

答案2

得分: 1

这可以通过以下向量化方式完成:

wr = np.repeat(weights[None,:], repeats=mat.shape[0],axis=0) 
# 将权重数组扩展以匹配矩阵数组的形状
# 将对角线填充为0
np.fill_diagonal(wr, 0)
wght_avg = np.average(mat, axis=-1, weights=wr)
print(wght_avg)
# >>array([2428.5       , 2442.23079848, 2442.076961  , 2436.53850163,
#    2427.76928603])
英文:

This can be done in this vectorized way:

wr = np.repeat(weights[None,:], repeats=mat.shape[0],axis=0) 
# expand weights array to match the shape of mat array
# fill the diagonal with 0
np.fill_diagonal(wght_repeat, 0)
wght_avg = np.average(mat, axis=-1, weights = wr)
print(wght_avg)
>>array([2428.5       , 2442.23079848, 2442.076961  , 2436.53850163,
   2427.76928603])

huangapple
  • 本文由 发表于 2023年6月6日 15:36:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76412376.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定