【问题标题】:How to use a linear index to access a 2D array in Python如何使用线性索引在 Python 中访问二维数组
【发布时间】:2017-01-28 21:10:47
【问题描述】:

我在 MATLAB 中有一段代码,我尝试将这段代码翻译成 Python。在 MATLAB 中,我可以这样写:

x = [1,2,3;4,5,6;7,8,9];

这只是一个 3*3 矩阵。然后如果我使用x(1:5),MATLAB 将首先将矩阵x 转换为 1*9 向量,然后返回一个 1*5 向量,如下所示:ans=[1,4,7,2,5]; 那你能告诉我python中哪一段简单的代码可以产生同样的结果吗?

【问题讨论】:

  • 新段落是通过在一个段落的结尾和下一个段落的开头之间放置一个空行来创建的。所以两个返回
  • 不完全是 MATLAB 的工作原理。 x(1:5) 只是按列优先顺序获取前五个元素,您可以像您描述的那样考虑,但 MATLAB 没有中间步骤。
  • 首先,感谢您告诉我如何生成新段落。然后考虑 Matlab 程序,我只是尝试描述 Matlab 返回的内容,并希望获得有关在 python 中执行相同工作的正确语句的答案。仍然感谢您的意见。

标签: python matlab matrix


【解决方案1】:

您可以将您的矩阵转换为numpy 数组,然后使用unravel_index 将您的线性索引转换为下标,然后您可以使用它来索引您的原始矩阵。请注意,下面的所有命令都使用 'F' 输入来使用列优先排序(MATLAB 的默认值)而不是行优先排序(numpy 的默认值)

import numpy as np

a = np.array([[1,2,3],[4,5,6],[7,8,9]])
inds = np.arange(5);

result = a[np.unravel_index(inds, a.shape, 'F')]
#   array([1, 4, 7, 2, 5])

此外,如果您想像 MATLAB 一样展平矩阵,您也可以这样做:

a.flatten('F')
#   array([1, 4, 7, 2, 5, 8, 3, 6, 9])

如果您要将一堆 MATLAB 代码转换为 python,强烈建议使用 numpy 并查看 the documentation on notable differences

【讨论】:

  • 非常感谢您的帮助。您的代码完美地解决了我遇到的问题。也感谢文档。
【解决方案2】:

我不确定 MATLAB 的 x(1:5) 语法应该做什么,但根据您想要的输出,它似乎是转置矩阵,将其展平,然后返回一个切片。这是如何在 Python 中做到这一点的:

>>> from itertools import chain
>>>
>>> x = [[1,2,3],
...      [4,5,6],
...      [7,8,9]]
>>>
>>> list(chain(*zip(*x)))[0:5]
[1, 4, 7, 2, 5]

【讨论】:

  • 我评论了 MATLAB 的功能:它以列优先顺序返回矩阵。 IE。如果 A=[1,2;3,4] A(:) 将返回 [1;2;3;4]`。不涉及转置,只是简单的旧列主要排序。您所说的“展平”显然是 Python 所做的,这是相同的过程,但按行优先顺序,所以是的,那么您必须转置一个矩阵才能在列优先中得到相同的结果。
  • 您的代码可以完美回答问题!但实际上,我遇到的问题更复杂。也谢谢你的回答!
【解决方案3】:

另一种直接访问二维数组而不制作转换副本的方法是使用整数除法和模运算符。

import numpy as np

# example array
rect_arr = np.array([[1, 2, 3, 10], [4, 5, 6, 11], [7, 8, 9, 12]])
rows, cols = rect_arr.shape

print("Array is:\n", rect_arr)
print(f"rows = {rows}, cols = {cols}")

# Access by Linear Indexing
# Reference:
# https://upload.wikimedia.org/wikipedia/commons/4/4d/Row_and_column_major_order.svg

total_elems = rect_arr.size

# Row major order
print("\nRow Major Sequence:")
for linear_index in range(total_elems):
    # do something with rect_arr[linear_index // cols][linear_index % cols]
    # Sequence will be 1, 2, 3, 10, 4, 5, 6, 11, 7, 8, 9, 12
    print(rect_arr[linear_index // cols][linear_index % cols])

# Columnn major order
print("\nColumn Major Sequence:")
for linear_index in range(total_elems):
    # do something with rect_arr[linear_index % rows][linear_index // rows]
    # Sequence will be 1, 4, 7, 2, 5, 8, 3, 6, 9, 10, 11, 12
    print(rect_arr[linear_index % rows][linear_index // rows])


# With unravel_index
# Row major order
row_indices = range(total_elems)
row_transformed_arr = rect_arr[np.unravel_index(row_indices, rect_arr.shape, "C")]
print(row_transformed_arr)

# Columnn major order
col_indices = range(total_elems)
col_transformed_arr = rect_arr[np.unravel_index(row_indices, rect_arr.shape, "F")]
print(col_transformed_arr)

在子图中有用:

# <df> is a date-indexed dataframe with 8 columns containing time-series data
fig, axs = plt.subplots(nrows=4, ncols=2)
rows, cols = axs.shape

# Order plots in row-major
for i, colname in enumerate(df):
    df[colname].plot(ax=axs[i // cols][i % cols], title=colname)
plt.show()

# Order plots in column-major
for i, colname in enumerate(df):
    df[colname].plot(ax=axs[i % rows][i // rows], title=colname)
plt.show()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-19
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 2016-05-28
    • 2020-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多