Mathematica中的条件数据处理

500*_*500 8 wolfram-mathematica data-structures

我正在尝试为Mathematica中的高效数据分析准备最好的工具.我有大约300列和100 000行.

什么是最好的技巧:

"删除","提取"或简单地"考虑"数据结构的一部分,用于绘制例如

我能想到的最棘手的例子之一是:

给定数据结构,

为第2列中的值等于x并且第8列中的值不同于y的每一行提取第1列到第3列,第6列到第9列以及最后一行

我也欢迎任何有关数据操作的一般建议.

Leo*_*rin 6

对于具有命名列的表中的数据的通用操作,我引用了这个我的解决方案,以获得类似的问题.对于任何特定情况,可能更容易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 = 4y=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创建,我认为这是一种非常强大的技术.

  • @ 500保留标题的另一个好理由是它们提供了一定程度的间接性并使您的解决方案更加健壮:您是否希望稍后更改表中列的顺序(例如,通过插入一些新列类型)在您的表中,或删除现有的,或只是交换列),使用标题名称进行的查询将保持有效,而具有显式索引的所有函数可能会变成垃圾.出于同样的原因,真正的SQL查询使用列名而不是数字索引. (2认同)