500*_*500 8 wolfram-mathematica data-structures
我正在尝试为Mathematica中的高效数据分析准备最好的工具.我有大约300列和100 000行.
什么是最好的技巧:
"删除","提取"或简单地"考虑"数据结构的一部分,用于绘制例如
我能想到的最棘手的例子之一是:
给定数据结构,
为第2列中的值等于x并且第8列中的值不同于y的每一行提取第1列到第3列,第6列到第9列以及最后一行
我也欢迎任何有关数据操作的一般建议.
对于具有命名列的表中的数据的通用操作,我引用了这个我的解决方案,以获得类似的问题.对于任何特定情况,可能更容易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]]]];
Run Code Online (Sandbox Code Playgroud)
这里发生的是,使用的函数是Select从您的规范自动生成的.例如(使用@Yoda的例子):
rows = Array[#1 #2 &, {5, 15}];
Run Code Online (Sandbox Code Playgroud)
我们需要定义列名(必须是没有值的字符串或符号):
In[425]:=
colnames = "c" <> ToString[#] & /@ Range[15]
Out[425]= {"c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11", "c12",
"c13", "c14", "c15"}
Run Code Online (Sandbox Code Playgroud)
(实际上,通常名称更具描述性).这是表格:
table = Prepend[rows, colnames];
Run Code Online (Sandbox Code Playgroud)
以下是你需要(我选择了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}}
Run Code Online (Sandbox Code Playgroud)
现在,对于单个查询,这看起来像是一种复杂的方法.但是你可以做很多不同的查询,例如
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}}
Run Code Online (Sandbox Code Playgroud)
和类似的.
当然,如果您的数据中存在特定的相关性,您可能会发现一种特定的特殊用途算法会更快.上述函数可以通过多种方式进行扩展,以简化常见查询(包括"all"等),或自动编译生成的纯函数(如果可能).
编辑
在哲学上,我确信许多Mathematica用户(包括我自己)发现自己不时地一次又一次地编写类似的代码.事实上,Mathematica具有简洁的语法,因此通常很容易为任何特定情况编写.但是,只要一个在某个特定域中工作(例如,表中的数据操作),对于许多操作来说,重复自己的成本会很高.我的示例在一个非常简单的设置中说明了一种可能的出路 - 创建一种特定于域的语言(DSL).为此,通常需要为其定义语法/语法,并将编译器从中编写到Mathematica(以自动生成Mathematica代码).现在,上面的例子是这个想法的一个非常原始的实现,但我的观点是Mathematica通常非常适合DSL创建,我认为这是一种非常强大的技术.