【问题标题】:How can I index numpy arrays with a list of ranges?如何使用范围列表索引 numpy 数组?
【发布时间】:2020-05-22 10:05:28
【问题描述】:

我正在从一系列 148 个时间序列图像中提取像素值,以获取有关荧光值的一些信息。 每个图像中的感兴趣区域由一系列不同长度的坐标定义 例如区域 1(存在于所有 148 个图像中)由 175 个坐标定义,而区域 2 由 107 个坐标定义。 我的问题是我已经到了一个长度为 148 的 numpy 数组的地步,这 148 个数组中的每一个都包含 11,000 个像素值。我想用 11,000 个不同的坐标范围对这些数组中的每一个进行子集化。因为坐标范围不同,数组不能平均分割,所以很难让它工作。这是我目前所拥有的:

# define a function to find out the lengths of each ROI coordinate lists: 

def number_of_coordinates_to_define_each_region(coordinates):
    length = []
    for arrays in coordinates:
        leng = len(arrays)
        length.append(leng)
    return length

coordinate_length = number_of_coordinates_to_define_each_region(coords)
print(coordinate_length)

OUT: [175, 107, 107, 95, 67, 106, 836, 74, 1054, 101, 72, 93, 181, 223, 671, 288, 123, 69, 121, 175, 317, 325, 189, 139, 494, 296, 244, 129, 282, 226, 236, 108, 134, 284, 117, 144, 97, 95, 193, 255, 182, 191, 285, 104, 91, 255, 60, 112, 142, 189, 73, 81, 133, 65, 148]

# these represent 55 regions of interest each with the associated number of coordinates

# function to make the coordinate lists ranges instead of single numbers 

def list_of_coordinate_ranges(coordinate_length):
    items = []
    for x in coordinate_length:
        item = range(x)
        items.append(item)
    return items

coordinate_arrays = list_of_coordinate_ranges(coordinate_length)
print(coordinate_arrays)

OUT: [range(0, 175), range(0, 107), range(0, 107), range(0, 95), range(0, 67), range(0, 106), range(0, 836), range(0, 74), range(0, 1054), range(0, 101), range(0, 72), range(0, 93), range(0, 181), range(0, 223), range(0, 671), range(0, 288), range(0, 123), range(0, 69), range(0, 121), range(0, 175), range(0, 317), range(0, 325), range(0, 189), range(0, 139), range(0, 494), range(0, 296), range(0, 244), range(0, 129), range(0, 282), range(0, 226), range(0, 236), range(0, 108), range(0, 134), range(0, 284), range(0, 117), range(0, 144), range(0, 97), range(0, 95), range(0, 193), range(0, 255), range(0, 182), range(0, 191), range(0, 285), range(0, 104), range(0, 91), range(0, 255), range(0, 60), range(0, 112), range(0, 142), range(0, 189), range(0, 73), range(0, 81), range(0, 133), range(0, 65), range(0, 148)]

# turn the list of pixel values into a numpy array and split 148 times to separate out into different images

pixel_collection = np.array(pixels)
pixel_collection_2 = np.split(pixel_collection, 148)

split_collection = []
for number in range(148):
    item_1 = pixel_collection_2[number]
    split_collection.append(item_1)

# subset each image with the ranges of coordinates

mean_pixels = []
for arrays in split_collection:
    for x in coordinate_arrays:
        items_2 = np.mean(arrays[x])
        mean_pixels.append(items_2)

我不会发布输出,但它基本上给了我每个范围的平均像素,但每次都从索引 0 开始,而不是 175 的子集,然后 175 之后的 107 的子集。

所以我的问题是如何将数组与范围进行子集化,但使其按顺序进行,而不是每次都从头开始?

抱歉问题太长了!

【问题讨论】:

  • 所以你想要[range(0, 175), range(175, 175+107) , ...]
  • 不完全是因为我想要子集 0-175、175-282、282-389 等
  • 这正是我的意思。在我看来,您正在做很多不必要的事情。我认为我们可以将其归结为更少的行。 pixels 到底是什么?那是一个形状为 (11000, 148) 的数组(或列表)吗?
  • pixels 是一个列表,我将其转换为 numpy 数组(1D,1650644 个像素值,它们是所有 148 帧的像素总和),然后将其拆分为 148 种方式,以便将其分离为图像帧.但随后在 for 循环中必须转换回 numpy b/c 拆分使其再次成为列表!

标签: python numpy for-loop subset


【解决方案1】:

简单来说,我假设我们只有 5 帧,每帧 10 像素。既然你说你有一个一维列表,我就从np.arange()开始。这将为我们提供一些用于演示的虚拟数据:

pixels = np.arange(50)

首先,我们可以重塑pixels,而不是使用np.split() 来获取数组列表

pixels = pixels.reshape((5, 10))

现在让我们假设感兴趣区域(每帧的 10 个像素)是索引 0-3、4-5 和 6-9。由于都是连续的,我们只需要指定下一个区域开始的位置即可:

split_indices = [4, 6]

您已经使用了np.split(),但是如果您将整数列表作为第二个参数传递,它将准确地为您提供这些小节。此外,还需要指定轴和数组的拆分:

splits = np.split(pixels, split_indices, axis=1)

最后,我们可以遍历这些分割并计算平均值:

mean_pixels = [s.mean(axis=1) for s in splits]

我们现在有一个数组列表,其中包含每帧中每个区域的平均像素值。我们可以把它堆叠成一个数组,打印出来会更好看:

mean_pixels = np.stack(mean_pixels)
print(mean_pixels.T)    # transpose to have each row represent one frame
# array([[ 1.5,  4.5,  7.5],
#        [11.5, 14.5, 17.5],
#        [21.5, 24.5, 27.5],
#        [31.5, 34.5, 37.5],
#        [41.5, 44.5, 47.5]])

【讨论】:

  • 非常感谢!当我仅将它用于 148 帧时,它会返回平均输出,但其中一些只是说:非常感谢!为了简单起见,我只在一个时间范围内尝试了代码,并得到了这个输出,其中一些人说“nan”?:[118.64, nan, nan, nan, nan, 118.7948717948718, 121.4958904109589, nan, 122.66836734693878, nan, nan, 119.14285714285714, 118.94318181818181, 118.42857142857143, 120.46875, nan, nan, nan, 119.1923076923077, 119.01851851851852, 116.7605633802817, 119.875, nan, nan, 118.89295774647887, nan, nan, nan, 117.26797385620915, nan, 117.8, nan]
  • nan 是“不是数字”。例如,您将其作为空数组的平均值。这可能是因为您的拆分索引可能是错误的:您需要将它们全部向下移动 1,因此您的第一个索引是 174,而不是 175。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-06
  • 2021-10-12
  • 1970-01-01
  • 2019-06-18
  • 2023-03-16
相关资源
最近更新 更多