我有一个对应于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
)和整数或布尔数组有效索引”
答案 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 }} 除此以外。但是,围绕原始数据框创建一个包装器非常简单。您还可以根据每个数据框行中出现的元组创建一个集合,然后简单地查询该集合是否包含在内。