【问题标题】:How to change all columns value of a matrix in Python?如何在 Python 中更改矩阵的所有列值?
【发布时间】:2020-02-28 01:48:05
【问题描述】:

正如标题所说,我想将所有列的值更改为相同的数组,除了 numpy 之外不使用任何外部库,也不使用 for、while 或类似的东西,因为我正在寻找的是效率。

我认为我可以使用切片来解决这个问题,因为你可以对行做到这一点。

# Initial matrix
a= [[0,0,0],
    [0,0,0],
    [0,0,0]]

# Wanted array to replace all columns with
b = [1,2,3]

# Matrix after replacement
a= [[1,1,1],
    [2,2,2],
    [3,3,3]]

这就是我想要的输出,但由于某种原因我还不能实现它,因为我想以一种简单的方式来实现它。我该怎么做?提前致谢。

【问题讨论】:

    标签: python arrays python-3.x slice


    【解决方案1】:

    创建新矩阵比实际“就地”替换列更简单。 我假设你的矩阵是正方形的。

    length = len(b)
    a = [ [b[i]] * length for i in range(length) ]
    

    结果

       [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
    

    现在,根据相关评论者的多次请求,我为矩形 A 添加了一个解决方案:

    length = len(b)
    width = len(a[0])
    a = [ [b[i]] * width for i in range(length) ]
    

    或者,更pythonic的风格

    width = len(a[0])
    a = [ [x] * width for x in b ]   
    

    【讨论】:

    • 这并不能解决问题。你测试过吗?
    • 更好,但您假设矩阵始终是正方形的。这个问题并不能保证这一点。你也应该解释你的答案;不要只是发布代码。
    • 这是完全错误的。 a= [[0], [0], [0]] b = [1,2,3] 将失败。 b 的长度告诉你a 的高度,而不是awidth。在这种情况下,您永远无法从 b 中猜出 width
    • @kaya3 是的,我假设是方阵。为什么主题启动器会在示例中提供一个正方形?无论如何,您将我的解决方案的概括放在您的答案中
    • @Poojan,它可能会失败
    【解决方案2】:

    使用列表推导的简单解决方案:

    a = [ [x]*len(row) for row, x in zip(a, b) ]
    

    这会创建一个新矩阵,而不是就地改变矩阵。如果你想就地改变它,你需要一个嵌套循环:

    for row, x in zip(a, b):
        for i in range(len(row)):
            row[i] = x
    

    【讨论】:

      【解决方案3】:
      a= [[0,0,0],
         [0,0,0],
         [0,0,0]]
      b = [1,2,3]
      
      for i, value in enumerate(b):
          a[i] = [value]*len(a[i])
      
      print(a)
      

      输出:

      [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
      

      【讨论】:

      • 此解决方案有效,但有些奇怪。它就地更新矩阵a,但这样做是通过创建新行而不是就地更新行来实现的。如果其他代码持有对其中一行的引用,这可能会导致一些非常微妙的错误,该行(因为它没有就地更新)将保持全零。我认为您应该就地更新所有内容,或者创建一个新矩阵而不改变旧矩阵;将两者混合使用可能没有那么有用。
      • 我不明白为什么这会是个问题。能详细点吗?
      • 假设我们用零定义a,那么我们定义a_alias = aa_row_alias = a[0]。更新a 时,更新应该是“就地”,这意味着a_aliasa_row_alias 的内容也会发生变化,因为它们只是更新数据的别名,更新应该是“不合适的”,在这种情况下,a_aliasa_row_alias 仍然引用带有零的旧矩阵。当您的代码运行时,a_alias 现在包含来自 b 的值,但a_row_alias 仍然有零;这将是令人惊讶的,并且可能是错误的来源。
      【解决方案4】:

      您的列表无效,所以我假设您的意思是 3 个列表的列表

      a = [
          [0, 0, 0],
          [0, 0, 0],
          [0, 0, 0],
      ]
      
      b = [1, 2, 3]
      
      for counter, value in enumerate(b):
          a[counter] = [value for i in a[counter]]
      
      print(a)
      

      enumerate 免费为您提供计数器。

      注意如果 b 中的元素比 a 多,这会抛出 index out of range 错误,所以如果你不确定,在替换之前检查长度。

      【讨论】:

      • 而不是使用列表推导来创建列表。您可以只使用[value]*length 语法。
      • 此解决方案有效,但有些奇怪。它就地更新矩阵a,但这样做是通过创建新行而不是就地更新行来实现的。如果其他代码持有对其中一行的引用,这可能会导致一些非常微妙的错误,该行(因为它没有就地更新)将保持全零。我认为您应该就地更新所有内容,或者创建一个新矩阵而不改变旧矩阵;将两者混合使用可能没有那么有用。
      【解决方案5】:

      很高兴为这个问题获得更多背景信息,因为目前几乎没有什么可以解决的。例如,您对数组ab 有多少控制权?甚至可能一开始就不需要此操作。

      目前,当数组与您的示例中的数组相似时,这是一个可行的解决方案。

      import numpy as np
      
      
      arr_1 = np.array([1, 2, 3])
      
      arr_1_col = arr_1.reshape((-1, 1))
      
      arr_2 = np.tile(A=arr_1_col, reps=3)
      

      注意:你在你的问题中提到了 NumPy,我不能推荐它。一旦你在做这些类型的任务,切换到 numpy 数组是非常有益的。

      【讨论】:

        猜你喜欢
        • 2020-04-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-17
        • 2021-09-10
        • 2017-03-29
        • 2018-01-19
        相关资源
        最近更新 更多