【问题标题】:Selecting a subset of columns in a matrix using values stored in another matrix in Python使用 Python 中存储在另一个矩阵中的值选择矩阵中的列子集
【发布时间】:2022-02-04 23:23:59
【问题描述】:

我正在尝试通过使用来自另一个较小矩阵的值来对矩阵进行子集化。每个中的行数相同,但较小的矩阵具有较少的列。较小矩阵中的每一列都包含较大矩阵中应引用的列的值。这是我所做的,以及希望更好地描述这一点的 cmets,以及我尝试过的。 (其中的皱纹是每行中要使用的列的值会发生变化......) 我试过谷歌,在 stackoverflow 上搜索等,但找不到我要找的东西。 (我最接近的是在圣人中称为 matrix_from_columns 的东西,这里没有使用它)所以我可能犯了一个非常简单的引用错误。 TIA, 米康西定

import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import numpy as np
from numpy.lib.stride_tricks import sliding_window_view

#Problem:  for each row in a matrix/image I need to replace
#          a value in a particular column in that row by a
#          weighted average of some of the values on either
#          side of that column in that row.  The wrinkle
#          is that the column that needs to be changed may
#          vary from row to row.  The columns that need to
#          have their values changes is stored in an array.
#
#          How do I do something like:
#           img[:, selectedcolumnarray] = somefunction(img,targetcolumnmatrix)
#
#          I can do this for setting the selectedcolumnarray to a value, like 0
#          But I am not figuring out how to select the targeted values to
#          average.

#dimensions of subset of the matrix/image that will be averaged
rows = 7
columns = 5

#weights that will be used to average surrounding values
the_weights = np.ones((rows,columns)).astype(float)*(1/columns)
print(the_weights)

#make up some data to create a set of column
# values that vary by row
y = np.asarray(range(0,rows)).astype(float)
x = -0.095*(y**2) - 0.05*y + 12.123
fit=[x.astype(int),x-x.astype(int),y]
print(np.asarray(fit)[0])

#create a test array, eg "image' of 20 columns that will have
# values in targeted columns replaced
testarray = np.asarray(range(1,21))
img = np.ones((rows,20)).astype(np.uint16)
img = img*testarray.T #give it some values
print(img)

#values of the rows that will be replaced
targetcolumn = np.asarray(fit)[0].astype(int)
print(targetcolumn)

#calculate the range of columns in each row that
#  will be used in the averaging
startcol = targetcolumn-2
endcol = targetcolumn+2
testcoords=np.linspace(startcol,endcol,5).astype(int).T
#this is the correct set of columns in the corresponding
#  row to use for averaging
print(testcoords)

img2=img.copy()
#this correctly replaces the targetcolumn values with 0
#  but I want to replace them with the sum of the values
#  in the respective row of testcoords, weighted by the_weights
img2[np.arange(rows),targetcolumn]=0

#so instead of selecting the one column, I want to select
# the block of the image represented by testcoords, calculate
# a weighted average for each row, and use those values instead
# of 0 to set the values in targetcolumn

#starting again with the 7x20 (rowsxcolumns) "image"
img3=img.copy()
#this gives me the wrong size, ie 7,7,5 when I think I want 7,5;
print(testcoords.shape)

#I thought "take" might help, but ... nope
#img3=np.take(img,testcoords,axis=1)

#something here maybe??? :
#https://stackoverflow.com/questions/40084931/taking-subarrays-from-numpy-array-with-given-stride-stepsize
# but I can't figure out what


##### plot surface to try to visualize what is going on ####
'''
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})

# Make data.
X = np.arange(0, 20, 1)
Y = np.arange(0, rows, 1)
X, Y = np.meshgrid(X, Y)
Z = img2

# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)

# Customize the z axis.
ax.set_zlim(0, 20)
ax.zaxis.set_major_locator(LinearLocator(10))
# A StrMethodFormatter is used automatically
ax.zaxis.set_major_formatter('{x:.02f}')

# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

【问题讨论】:

  • 你检查过documentation吗?高级索引技术有很好的参考。
  • 是的,我看过了。而且该示例是可重现的,即它按原样运行
  • 可重现?是的。最小?绝对不。抱歉,但要求人们通读所有这些代码,而所有这些 cmets 对那些自愿花时间帮助你的人来说并不是特别有礼貌。您需要提供更简洁的问题陈述,包括示例输入和预期输出。
  • 不要将“已解决”编辑到您的问题标题中。单击答案旁边的复选框是唯一标记问题已解决的正确方法。 (是的,在您接受自己的答案之前有一段延迟;我们的想法是让问题保持足够长的时间,以便考虑和评估提出的任何其他答案)。

标签: python matrix subset


【解决方案1】:

事实证明“take_along_axis”可以解决问题:

imgsubset = np.take_along_axis(img3,testcoords,axis=1)
print(imgsubset)
newvalues = imgsubset * the_weights
print(newvalues)
newvalues = np.sum(newvalues, axis=1)
print(newvalues)
img3[np.arange(rows),targetcolumn] = np.round(newvalues,0)
print(img3)

(使用非平凡权重时会变得更加明显。)

感谢收听... 米康西定

【讨论】:

    猜你喜欢
    • 2014-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-28
    • 1970-01-01
    • 2019-06-27
    • 2020-08-31
    • 2015-08-08
    相关资源
    最近更新 更多