如何将 xyz 坐标的 Dataframe 转换为形状的二进制数组 (272, 512, 512)

How to transform a Dataframe of xyz coordinates into a binary array of shape (272, 512, 512)

我有一个对应于 3D 中心线 (x,y,z) 的数据框。我想将 Dataframe 转换为形状为 (272, 512, 512) 的二进制数组。 Dataframe 中的 z 值范围约为 40-160,它们对应于数组中的第一列。 x 和 y 值分别对应于数组中的第二列和第三列。任何不在 Dataframe 中的 xyz 值都应该对应于数组中的 0,任何存在的值都应该对应于 1。考虑到每个 plane/slice 可能在数组中有多个 1,关于如何做到这一点的任何想法?

如果我将 Dataframe 限制为每个唯一的 z 值只有一行(每个切片一个点),但实际数据每个唯一的 z 值有多个行,我就能够做到这一点。

Here is what the header of the Dataframe looks like

这是适用于下采样数据帧的代码(每个唯一 z 值只有一行):

def dataframe_to_binary_array(df):
    '''
    THIS FUNCTION TAKES IN A DOWNSAMPLED DATAFRAME AND CONVERTS IT TO A 3D
    BINARY ARRAY THAT IS THE SAME SHAPE AS THE ORIGINAL DICOM STACK
    '''
    empty_array = np.zeros([272, 512, 512], dtype='int64')
    z_column = df['Z']

    for z in z_column:
        z_df = df[z_column == z]

        for k in range(0, 272):
            x = z_df['X']
            y = z_df['Y']
            empty_array[z, x, y] = 1

    return empty_array

这是我为真正的 Dataframe 编写的代码尝试:

def dataframe_to_binary_array_new(df):
    '''
    THIS FUNCTION TAKES IN A DOWNSAMPLED DATAFRAME AND CONVERTS IT TO A 3D
    BINARY ARRAY THAT IS THE SAME SHAPE AS THE ORIGINAL DICOM STACK
    '''
    empty_array = np.zeros([272, 512, 512], dtype='int64')
    z_column = df['Z']

    for i in range(0,272):
        z_df = df[z_column == i]

        for row in z_df:
            x_col = z_df['X'].to_numpy()
            y_col = z_df['Y'].to_numpy()

            for x_element in x_col:
                x = int(x_element)

            for y_element in y_col:
                y = int(y_element)
                empty_array[i,x,y] = 1


    return empty_array

我得到的错误信息是"IndexError: only integers, slices (:), ellipsis (...), numpy.newaxis (None) and integer or boolean arrays are valid indices"

我会以不同的方式来解决这个问题。如何遍历原始数据框的行。然后使用每个数据框行的坐标将 empty_array 中的适当元素设置为 1.

下面是一些示例代码。 empty_array 更名为 binary_array。您可能需要将坐标从浮点数转换为整数,然后才能用作 binary_array.

中的索引
# x, y, z are integers from [0, 10)
n = 10

binary_array = np.zeros([n]*3)

# Builds 10 example coordinates
df = pd.DataFrame(np.random.randint(n, size=(10,3)), columns=list('XYZ'))

for idx, coord in df.iterrows():
    x, y, z = tuple(coord)
    binary_array[x, y, z] = 1

作为框架挑战,我会请您考虑为什么您要将其更改为 3D 阵列。您的数组将有 7100 万个条目。与数据框的大小相比如何?

您可能不是为了拥有 3D 而创建 3D 阵列。您有一些想要对 3D 阵列执行的操作。您应该考虑使用 3D 阵列是否真的更容易实现这些事情。据推测,如果元组 (x,y,z) 对应于原始数据帧中的一行,并且 0 否则。但是围绕执行此操作的原始数据框创建包装器相当简单。您还可以使用出现在每个数据框行中的元组创建一个集合,然后简单地查询该集合是否包含。