Для общего манипулирования данными в таблице с именованными столбцами я отсылаю вас к этому моему решению для аналогичного вопроса.В любом конкретном случае было бы проще написать функцию для Select
вручную.Тем не менее, для многих столбцов и множества различных запросов шансы испортить индексы высоки.Вот модифицированное решение из упомянутого поста, которое обеспечивает более дружественный синтаксис:
Clear[getIds];
getIds[table : {colNames_List, rows__List}] := {rows}[[All, 1]];
ClearAll[select, where];
SetAttributes[where, HoldAll];
select[cnames_List, from[table : {colNames_List, rows__List}], where[condition_]] :=
With[{colRules = Dispatch[ Thread[colNames -> Thread[Slot[Range[Length[colNames]]]]]],
indexRules = Dispatch[Thread[colNames -> Range[Length[colNames]]]]},
With[{selF = Apply[Function, Hold[condition] /. colRules]},
Select[{rows}, selF @@ # &][[All, cnames /. indexRules]]]];
Здесь происходит то, что функция, используемая в Select
, генерируется автоматически из ваших спецификаций.Например (используя пример @ Yoda):
rows = Array[#1 #2 &, {5, 15}];
Нам нужно определить имена столбцов (это должны быть строки или символы без значений):
In[425]:=
colnames = "c" <> ToString[#] & /@ Range[15]
Out[425]= {"c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11", "c12",
"c13", "c14", "c15"}
(на практике обычно это именаболее наглядны, конечно).Вот таблица:
table = Prepend[rows, colnames];
Вот оператор SELECT, который вам нужен (я выбрал x = 4
и y=2
):
select[{"c1", "c2", "c3", "c6", "c7", "c8", "c9", "c15"}, from[table],
where["c2" == 4 && "c8" != 2]]
{{2, 4, 6, 12, 14, 16, 18, 30}}
Теперь для одного запроса:это может выглядеть как сложный способ сделать это.Но вы можете выполнять много разных запросов, таких как
In[468]:= select[{"c1", "c2", "c3"}, from[table], where[EvenQ["c2"] && "c10" > 10]]
Out[468]= {{2, 4, 6}, {3, 6, 9}, {4, 8, 12}, {5, 10, 15}}
и т. П.
Конечно, если в ваших данных есть определенные корреляции, вы можете найти специальный алгоритм специального назначения, которыйбудет быстрееПриведенная выше функция может быть расширена различными способами, чтобы упростить общие запросы (включая «все» и т. Д.) Или автоматически скомпилировать сгенерированную чистую функцию (если это возможно).
РЕДАКТИРОВАТЬ
В философской заметке я уверен, что многие пользователи Mathematica (включая меня) время от времени оказывались, снова и снова создавая подобный код.Тот факт, что Mathematica имеет краткий синтаксис, часто очень легко писать для любого конкретного случая.Однако до тех пор, пока кто-то работает в какой-то конкретной области (как, например, манипуляции с данными в таблице), стоимость повторения будет высокой для многих операций.То, что мой пример иллюстрирует в очень простой настройке, является одним из возможных выходов - создать домен-специфический язык (DSL).Для этого обычно нужно определить синтаксис / грамматику для него и написать компилятор из него в Mathematica (чтобы автоматически генерировать код Mathematica).Теперь приведенный выше пример является очень примитивной реализацией этой идеи, но я хочу сказать, что Mathematica, как правило, очень хорошо подходит для создания DSL, что, я думаю, является очень мощной техникой.