【问题标题】:How can I reshape a 2D array into 1D in python?如何在 python 中将 2D 数组重塑为 1D?
【发布时间】:2022-11-03 22:11:39
【问题描述】:

让我再次编辑我的问题。我知道flatten 是如何工作的,但我正在寻找是否可以删除inside braces 和简单的two outside braces,就像在MATLAB 中一样,并保持相同的shape of (3,4)。这里是arrays inside array,我只想有一个数组,这样我就可以轻松地绘制它也得到相同的结果,它在Matlab 中。 例如我有以下matrix(这是数组内的数组):

s=np.arange(12).reshape(3,4)
print(s)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

是否有可能reshapeflatten() 得到这样的结果:

[ 0  1  2  3
  4  5  6  7
  8  9 10 11]

【问题讨论】:

  • 是您感兴趣的打印方式吗?因为,您似乎已经知道flatten()(否则您甚至连括号都不会添加),所以我认为所有帮助您获得[ 0 1 2 3 4 5 6 7 8 9 10 11] 的答案都不会让您真正感兴趣(奇怪的是,他们都不感兴趣, 建议只使用.flatten())。
  • 如果您感兴趣的是 flatten 数组仍然打印 3 行,那么,不。您可以看到 here 想要这样做的人从完全相反的操作开始:将 1d 数组重塑为 2d 数组。那是印刷问题。数组的值不是它的打印方式。一维数组值不包含换行符。这只是一堆数字。
  • (注意:flatten 和 reshape(-1) 的区别在于 flatten 创建一个新副本,而 reshape(-1) 只是相同数据的视图)
  • 注意(不知道您是否在编辑答案时收到通知),我已经编辑了我的答案以包含一个新想法,即子类化。这可能效果很好,具体取决于您需要对阵列做什么。

标签: python arrays matrix flatten


【解决方案1】:

简单地说,使用带有 -1 作为形状的 reshape 函数应该这样做:

print(s)
print(s.reshape(-1))

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[ 0  1  2  3  4  5  6  7  8  9 10 11]

【讨论】:

  • 我赞成,因为这是扁平化(没有复制)的方式,而不是所有嵌套的 for 循环,慢了大约 1000 倍。但我很确定这不是 OP 的真正问题,他想知道如何让 flatten 阵列仍然以 3 行显示。如果我猜对了。
【解决方案2】:

第一个答案

如果我正确理解了您的问题(还有 4 个其他答案说我没有),您的问题不是如何 flatten()reshape(-1) 一个数组,而是如何确保即使在重塑之后,它仍然显示每个元素 4 个线。

我不认为你可以,严格来说。数组只是一堆元素。它们不包含有关我们希望如何查看它们的指示。那是打印问题,您应该在打印时解决。您可以在 [here][1] 看到想要这样做的人......从在 2D 中重塑数组开始。

话虽如此,在不创建自己的打印功能的情况下,您可以使用np.set_printoptions 控制 numpy 显示数组的方式。

尽管如此,它还是很棘手,因为这个函数只允许您指定每行打印多少个字符,而不是元素。所以你需要知道每个元素需要多少个字符来强制换行。

在您的示例中:

np.set_printoptions(formatter={"all":lambda x:"{:>6}".format(x)}, linewidth=7+(6+2)*4)

格式化程序确保每个数字使用 6 个字符。 线宽,考虑到 "array([" 部分,以及结束 "])" (9 chars) 加上每个元素之间的 2 ", ",知道我们想要 4 个元素,必须是 9+6×4+2× 3:“array([...])” 9 个字符,每 4 个数字 6×4,每 3 个“,” 分隔符 2×3。或 7+(6+2)×4。

您只能将其用于一次打印

with np.printoptions(formatter={"all":lambda x:"{:>6}".format(x)}, linewidth=7+(6+2)*4):
    print(s.reshape(-1))

一段时间后编辑:子类

我想到的另一种方法是将ndarray 子类化,使其行为符合您的要求

import numpy as np


class MyArr(np.ndarray):
# To create a new array, with args ls: number of element to print per line, and arr, normal array to take data from
    def __new__(cls, ls, arr):
        n=np.ndarray.__new__(MyArr, (len(arr,)))
        n.ls=ls
        n[:]=arr[:]
        return n

    def __init__(self, *args):
        pass

    # So that this .ls is viral: when ever the array is created from an operation from an array that has this .ls, the .ls is copyied in the new array
    def __array_finalize__(self, obj):
        if not hasattr(self, 'ls') and type(obj)==MyArr and hasattr(obj, 'ls'):
            self.ls=obj.ls

    # Function to print an array with .ls elements per line
    def __repr__(self):
        # For other than 1D array, just use standard representation
        if len(self.shape)!=1:
            return super().__repr__()

        mxsize=max(len(str(s)) for s in self)
        s='['
        for i in range(len(self)):
            if i%self.ls==0 and i>0:
                 s+='
 '
            s+=f'{{:{mxsize}}}'.format(self[i])
            if i+1<len(self): s+=', '
        s+=']'
        return s

现在你可以使用这个MyArr 来构建你自己的一维数组

MyArr(4, range(12))

节目

[ 0.0,  1.0,  2.0,  3.0, 
  4.0,  5.0,  6.0,  7.0, 
  8.0,  9.0, 10.0, 11.0]

您可以在任何一维 ndarray 合法的地方使用它。大多数时候,.ls 属性会随之而来(我说“大部分时间”,因为我不能保证某些函数不会构建新的 ndarray,并用来自这个的数据填充它们)

a=MyArr(4, range(12))
a*2
#[ 0.0,  2.0,  4.0,  6.0, 
#  8.0, 10.0, 12.0, 14.0, 
# 16.0, 18.0, 20.0, 22.0]
a*a
#[  0.0,   1.0,   4.0,   9.0, 
#  16.0,  25.0,  36.0,  49.0, 
#  64.0,  81.0, 100.0, 121.0]
a[8::-1]
#[8.0, 7.0, 6.0, 5.0, 
# 4.0, 3.0, 2.0, 1.0, 
# 0.0]

# It even resists reshaping
b=a.reshape((3,4))
b
#MyArr([[ 0.,  1.,  2.,  3.],
#       [ 4.,  5.,  6.,  7.],
#       [ 8.,  9., 10., 11.]])
b.reshape((12,))
#[ 0.0,  1.0,  2.0,  3.0, 
#  4.0,  5.0,  6.0,  7.0, 
#  8.0,  9.0, 10.0, 11.0]

# Or fancy indexing
a[np.array([1,2,5,5,5])]
#[1.0, 2.0, 5.0, 5.0,
# 5.0]


# Or matrix operations
M=np.eye(12,k=1)+2*M.identity(12) # Just a matrix
M@a
#[ 1.0,  4.0,  7.0, 10.0, 
# 13.0, 16.0, 19.0, 22.0, 
# 25.0, 28.0, 31.0, 22.0]
np.diag(M*a)
#[ 0.0,  2.0,  4.0,  6.0, 
#  8.0, 10.0, 12.0, 14.0, 
# 16.0, 18.0, 20.0, 22.0]

# But of course, some time you loose the MyArr class
import pandas as pd
pd.DataFrame(a, columns=['v']).v.values
#array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11.])

  [1]: https://stackoverflow.com/questions/25991666/how-to-efficiently-output-n-items-per-line-from-numpy-array

【讨论】:

    【解决方案3】:

    你可以使用itertools.chain

    from itertools import chain
    import numpy as np
    s=np.arange(12).reshape(3,4)
    print(list(chain(*s)))
    # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    print(s.reshape(12,)) # this will also work
    print(s.reshape(s.shape[0] * s.shape[1],)) # if don't know number of elements before hand
    

    【讨论】:

      【解决方案4】:

      试试.ravel()

      s = np.arange(12).reshape(3, 4)
      print(s.ravel())
      

      印刷:

      [ 0  1  2  3  4  5  6  7  8  9 10 11]
      

      【讨论】:

        猜你喜欢
        • 2016-06-30
        • 1970-01-01
        • 2023-03-14
        • 2016-01-17
        • 2021-02-25
        • 1970-01-01
        • 2020-11-16
        • 2020-04-22
        • 1970-01-01
        相关资源
        最近更新 更多