Как преобразовать Dataframe из координат XYZ в двоичный массив формы (272, 512, 512) - PullRequest
0 голосов
/ 22 марта 2020

У меня есть Dataframe, который соответствует трехмерной центральной линии (x, y, z). Я хочу превратить Dataframe в двоичный массив с формой (272, 512, 512). Значения z в кадре данных варьируются от 40 до 160, и они соответствуют первому столбцу в массиве. Значения x и y соответствуют второму и третьему столбцам в массиве соответственно. Любое значение xyz, отсутствующее в кадре данных, должно соответствовать 0 в массиве, а любое имеющееся значение должно соответствовать 1. Любые идеи о том, как сделать это, учитывая, что каждая плоскость / срез может иметь несколько единиц в массиве?

Я смог бы выполнить это sh, если бы я ограничил Dataframe только одной строкой на уникальное значение z (одна точка для каждого среза), но реальные данные имеют несколько строк на уникальное значение z.

Вот как выглядит заголовок Dataframe

Этот код работает для пониженной дискретизации Dataframe (только одна строка на уникальное значение 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 голосов
/ 22 марта 2020

В качестве испытания кадра я бы попросил вас рассмотреть , почему вы меняете его на 3D-массив. Ваш массив будет иметь 71 миллион записей. Как это соотносится с размером вашего фрейма данных?

Вероятно, вы не создаете 3D-массив только для того, чтобы иметь 3D. У вас есть кое-что, что вы хотите сделать с 3D-массивом. Вы должны подумать, действительно ли эти вещи проще реализовать с помощью трехмерного массива. Предположительно, вам нужен объект my_array такой, что вы можете сделать my_array.get_value(x,y,z) и получить 1, если кортеж (x,y,z) соответствует строке в исходном кадре данных, и 0 в противном случае. Но это довольно просто создать оболочку вокруг исходного кадра данных, которая делает это. Вы также можете создать набор из кортежей, которые появляются в каждой строке кадра данных, а затем просто запросить набор для включения.

0 голосов
/ 22 марта 2020

Я бы пришел к этому по-другому. Как насчет итерации по строкам исходного кадра данных. Затем используйте координаты из каждой строки информационного кадра, чтобы установить соответствующий элемент в 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...