获取一个3D或4D数组作为输入,并在外部脚本的函数中将其重塑为2D数组



好吧,我的问题比将3D或4D阵列重塑为2D阵列更具体一些。

我正在为3D或4D阵列的前端处理编写脚本。

我想从外部脚本中调用一个函数,3D数组将作为唯一输入提供。所需的输出应该是2D阵列。

更详细地说,3D或4D阵列将具有维度(x,y,t)或(x,y,z,t),其中x,y和z是空间维度,t是时间。基本上,这就是包含非定常流数据的方式。

现在,我想将其重塑为具有shape([x*y*z,t])的2D阵列。但是,这应该只使用多维数组作为输入。我不想把x、y、z和t作为输入。

有人能帮我写一个函数吗?

类似

def前端(数据):

  • 检查数据.shape
  • 使用len(data)命令获取x、y、z、t值
  • 将数据重塑为([x*y*z,t])
  • 返回整形后的数据

更新:很抱歉我说得不太清楚。我的问题恰恰在于形状。例如,我在x方向上有100步,在y方向上有50步,在z方向上有10步,在时间方向上有20步。也就是说,数组具有维度([100,50,10,20])。现在,我需要将这个([100,50,10,20])数组重新整形为([50000,20])数组。这可以通过普通的"整形"命令来完成。现在,问题是,我只从外部脚本向函数提供数据数组,而我不知道它的维度。我需要找到数组的X维、Y维、Z维和t维,然后我需要将这个4D数组重塑为具有维度([X*Y*Z,t])的2D数组。最后,我必须得到这个2D数组作为输出。

更新:

问题的更新表明函数frontend()应该只使用一个数组(python列表)。这将是这种情况的简化解决方案:

def frontend(data):
  return [reduce(lambda a, b: a*b, data[:-1]), data[-1]]

返回列表的第一个元素是通过乘以data中除最后一个元素(data[:-1])之外的所有元素生成的。这将是[x, y][x, y, z]。返回列表的第二个元素只是datadata[-1])的最后一个元素。在3D和4D情况下,这将是t

示例用法:

>>> frontend([100,50,10,20])
[50000, 20]
>>> frontend([100,50,20])
[5000, 20]

Python 3的更新:

在Python3中,不再有reduce()函数。在不导入任何内容的情况下,您需要使用一个循环:

def frontend(data):
  product = 1
  for elem in data[:-1]:
    product = product * elem
  return [product, data[-1]]

用法同上:

>>> frontend([100,50,10,20])
[50000, 20]

元组列表的以前解决方案:

我不完全确定你说的"checkdata.shape"是什么意思。我确实把它解释为测试一个元素有多少维度。我正在展示两个版本。第一种方法是检查数据的第一个元素中的值的数量,第二种方法是简单地将一个数据元素中除最后一个之外的所有值相乘,然后将最后一个作为所得"2D"元素的第二个值相加:

# example data:
data_5d = [(1,2,3,4,5), (5,6,7,8,9)]
data_4d = [(1,2,3,4), (5,6,7,8)]
data_3d = [(1,2,3), (4,5,6)]
data_2d = [(1,2), (2,5)]
data_inconsistent = [(1,2,3,5), (8,9)]

# Version handling only 3D and 4D data:
# =====================================
def frontend(data):
  #check data.shape:
  # get number of dimensions by checking first element:
  dimensions = len(data[0])
  #optain values and reshape:
  if dimensions == 4:
    return [[x*y*z, t] for x, y, z, t in data]
  elif dimensions == 3:
    return [[x*y, t] for x, y, t in data]
  else:
    #handle error?
    return []
print "frontend():"
print "5D: ", frontend(data_5d)
print "4D: ", frontend(data_4d)
print "3D: ", frontend(data_3d)
print "2D: ", frontend(data_2d)
# this would raise an exception:
#print frontend(data_inconsistent)

# General Version
# ===============
def frontendx(data):
  return [[reduce(lambda a, b: a*b, elem[:-1]), elem[-1]] for elem in data]
print "nfrontendx():"
print "5D: ", frontendx(data_5d)
print "4D: ", frontendx(data_4d)
print "3D: ", frontendx(data_3d)
print "2D: ", frontendx(data_2d)
print "?D: ", frontendx(data_inconsistent)

输出:

frontend():
5D:  []
4D:  [[6, 4], [210, 8]]
3D:  [[2, 3], [20, 6]]
2D:  []
frontendx():
5D:  [[24, 5], [1680, 9]]
4D:  [[6, 4], [210, 8]]
3D:  [[2, 3], [20, 6]]
2D:  [[1, 2], [2, 5]]
?D:  [[6, 5], [8, 9]]

感谢Pascal Rosin的解决方案。它运行得很好。

此外,我还想出了另一个解决方案。

由于我处理的是4D/3D/2D数组,所以我在外部脚本上编写了一个函数,导入它,然后在主脚本上使用它。

我使用ndarray.ndim来找到尺寸并适当地重塑它。

# Passing data as input
def frontend(data):
    if data.ndim == 4:
        data = data.reshape([data.shape[0]*data.shape[1]*data.shape[2],data.shape[3]])
        return data
    elif data.ndim == 3:
        data = data.reshape([data.shape[0]*data.shape[1],data.shape[2]])
        return data
    elif data.ndim == 2:
        return data
    else:
        text = 'unrecognized shape'
        print str(text)

这也非常有效。

最新更新