Октава: различия между структурой и массивом ячеек - PullRequest
0 голосов
/ 18 июня 2020

Спровоцированный этим вопросом и опубликованными комментариями / ответами, я задал другой вопрос:

Какие функции доступны в Массивах ячеек , которые являются не в Structures , и наоборот, в Octave?

Я мог бы собрать следующее:

В массивах ячеек:

  1. Может работать сразу с полными «столбцами» (полями в структуре lin go).

В структурах:

  1. Именованные поля.

1 Ответ

0 голосов
/ 18 июня 2020

Я думаю, что лучший способ ответить на этот вопрос, а не говорить о том, насколько они похожи, - это указать, чем они отличаются.

Кроме того, поскольку вы, похоже, рисуете эквиваленты (и, возможно, сбивающие с толку) концепции из других языков может быть поучительно указать на сходство с конструкциями из других популярных языков, а именно R и python.

Во всех вышеперечисленных языках существует концепция

  • «массив»: rect angular коллекция элементов того же типа , которые могут иметь одно или несколько измерений и обычно гарантированно занимают непрерывную область в памяти

  • «список»: набор элементов, которые могут быть разных типов , не обязательно быть прямоугольными angular (т.е. 'зубчатый'), как правило, только 1D (но может быть многомерным или содержать вложенные списки), и его элементы не обязательно занимают непрерывную область в памяти

  • a "dict": набор элементов, которые ch похожи на список, но дополнены тем фактом, что к ним можно получить доступ с помощью «ключа», а не только по индексу.

  • «таблица» (?): горизонтальная конкатенация столбцов одинакового размера, каждый из которых идентифицируется «заголовком столбца»

Октава

В октаве наиболее близким к концепции «массива» является «объект». array, (где 'объект' может быть любым, но обычно числовым) e, g, [1,2: 3,4].

Наиболее близким к понятию «список» является массив ячеек, например {[1,2], верно; "Джон"}. Чтобы проиндексировать массив ячеек и получить содержимое ячейки по определенному индексу, вы используете {}. Однако октавные массивы ячеек немного отличаются в том смысле, что их также можно рассматривать как «массивы объектов», где элементами объекта являются «ячейки», которые вы можете рассматривать как ссылки на содержащиеся в них объекты. Это означает, что вы можете построить массив ячеек и проиндексировать его с помощью () в качестве обычного массива, возвращая подмассив ячеек (то есть другой массив ячеек). Кроме того, ячейка может содержать другой массив ячеек в качестве своего содержимого (т.е. массивы ячеек могут быть вложенными).

Наиболее близкой к концепции "dict" является структура. Это позволяет вам создать объект, который может иметь «поля», так что для каждого поля вы можете присвоить значение.

Python

Напротив, в python вы этого не делаете. есть массивы. У вас есть только списки и диктовки. Чтобы получить функциональность массива, вам нужно полагаться на внешние модули (например, numpy), которые принимают список в качестве аргумента для преобразования в тип массива. Списки Python также всегда одномерные (но могут быть вложенными).

Python dicts фактически ведут себя так же, как октавные структуры. Есть несколько крошечных концептуальных различий, но они фактически эквивалентны конструкциям.

R

R, вероятно, вызывает наибольшую путаницу, потому что R позволяет вам выделять имен к элементам как массивов, так и списков, и позволяет вам получить доступ к обоим, используя индекс или назначенное имя.

Но R по-прежнему имеет векторный тип, например c (1,2,3 ), который, несмотря на то, что ему также могут быть присвоены имена, например c (a = 1, b = 2, c = 3), он по-прежнему требует, чтобы элементы были одного типа, иначе R будет преобразовывать в наименьший общий знаменатель. (например, c (1, '2') преобразует оба элемента в строки).

Затем у вас есть списки, которые в основном представляют собой что-то вроде комбинированных «списков» и «dicts». Если у вас есть список (1, 2, 3), у вас есть функция «список», а если у вас есть список (a = 1, b = 2, c = 3), у вас есть функция «dict». Если вы обращаетесь к элементу списка с помощью оператора [], результат выражается в виде другого списка (аналогично тому, как массивы в октаве могут быть проиндексированы с помощью ()), тогда как если вы индексируете список с помощью [[]] оператор, вы получаете только «содержимое» (аналогично тому, как если бы вы индексировали массив ячеек в октаве с помощью {}).

«Таблицы»: кадры данных против словарных знаков против структур

Теперь, в R у вас также есть фреймы данных. По сути, это список с именами (т.е. 'dict'), где все элементы являются векторами одинаковой длины (но могут быть разных типов), например, data.frame( list( a=1:3, b=c('one', 'two', 'three') ) ); обратите внимание, что выражение этого в виде data.frame, а не простого списка просто приводит к другому поведению (например, печати), но в остальном базовый объект тот же (что вы можете подтвердить, набрав unclass(df).

In python, мы можем отметить, что фрейм данных pandas ведет себя таким же образом (т.е. фрейм данных pandas инициализируется с помощью dict, ключи которого содержат значения, которые являются векторами одинакового размера).

Следовательно, поскольку фрейм данных является в основном список равных векторов, самый простой способ реализовать функциональность фрейма данных в октаве - создать структуру, поля которой являются векторами равного размера. или , если вам не нужны имена полей и вы с радостью получите доступ к своим содержали массивы по «индексу столбца», тогда вы можете создать массив ячеек и хранить в каждой ячейке свои числовые массивы «данных» одинакового размера.

Есть ли в ячейках «столбцы», как подразумевается в вопросе?

Нет. Если вы хотите выполнять векторизованные операции, вы не можете делать это со столбцами массив ячеек . для выполнения векторизованных операций с массивами.

На самом деле, если то, что вы ищете, является эквивалентом фрейма данных, где каждый «столбец» представляет числовой вектор, эквивалентом этого является структура, в которой вы присвоить числовой вектор полю.

Другими словами, эквиваленты фреймов данных на различных языках:

  • Python: pandas.DataFrame( { 'col1': [1,2], 'col2': [3,4] })

  • R: data.frame( list( col1=c(1,2), col2=c(3,4) ) )

  • octave: struct( 'col1', [1,2], 'col2', [3,4] )

    Сказав это, вы можете предпочесть более «табличный» вывод. Вы можете написать для этого свою собственную функцию или попробовать пакет dataframe от octave forge, который предоставляет класс именно для этого.

В качестве примера вот один фрагмент, который вы могли бы легко преобразовать в функцию и улучшить, добавив всевозможные навороты, такие как цвет и т.д. c.

fprintf( '%4s %5s %5s\n', '', fieldnames(S){:} ), for i = 1 : length(S.col1), fprintf( '%4d %5.3f %5.3f\n', i, num2cell( structfun(@(x) x(i), S) ){:} ), end
   col1  col2
1 1.000 3.000
2 2.000 4.000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...