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

时间:2020-03-22 03:37:33

标签: python arrays pandas dataframe medical

我有一个对应于3D中心线(x,y,z)的数据框。我想将数据框转换为形状为(272、512、512)的二进制数组。数据框的z值范围在40-160之间,它们对应于数组中的第一列。 x和y值分别对应于数组中的第二列和第三列。不在数据帧中的任何xyz值应对应于数组中的0,并且存在的任何值应对应于1。关于如何考虑每个平面/切片的此方法的任何想法都可能在数组中具有多个1。

如果我将数据框限制为每个唯一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

这是我为真正的数据框编写代码的尝试:

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:仅整数,切片(:),省略号(...),numpy.newaxis(None)和整数或布尔数组有效索引”

2 个答案:

答案 0 :(得分:0)

我会以不同的方式来。如何遍历原始数据帧的行。然后使用每个数据帧行中的坐标将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

答案 1 :(得分:0)

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

您可能不是为了拥有3D而创建3D阵列。您想对3D阵列做一些事情。您应该考虑使用3D阵列是否真的更容易实现这些功能。假定您想要一个对象my_array,以便如果元组my_array.get_value(x,y,z)对应于原始数据帧中的一行,则1可以得到(x,y,z),并且{{1 }} 除此以外。但是,围绕原始数据框创建一个包装器非常简单。您还可以根据每个数据框行中出现的元组创建一个集合,然后简单地查询该集合是否包含在内。