从txt文件导入数据到Mathematica

5
考虑以下在Mathematica中的列表:
a = {
   {
    {0, 0, 0}, {1, 0, 0}, {1, 1, 0}
    },
   {
    {0, 0, 1}, {1, 0, 1}, {1, 1, 1}
    }
   };

现在,调用:
Export["test.dat", a]

然后

b = Import["test.dat"]

您会发现在最后a并不等于b。这是一个特性还是一个错误?此外,我想要导入格式如下的列表:{P1,P2,P3...,Pn}其中Pi={v1,v2,v3,...,vm},每个vi={x,y,z},其中x、y、z是表示顶点vi的坐标的数字。这应该是一个多边形列表。请问我应该如何设置我的.dat文件,以便我可以用Mathematica读取它,并且我应该如何读取它呢?我试图模仿上面的Export["test.dat",a]输出,但是我发现了另一个问题。 我在这里找到了一个相关的问题,但无法使答案对我有用... 有什么想法吗?谢谢!
4个回答

5
你需要指定导入/导出的确切格式,否则Mathematica可能无法猜测正确的格式。因此,你的问题归结为什么文本格式适合存储3D数组?如果你使用Mathematica,最简单的方法可能是使用Mathematica的表达式语法导出表达式,即Export["data.m", a, "Package"]。这种格式相对于其他语言来说比较容易编写(但解析起来不太容易)。你的另一个选择是为你的3D数据构建一些新的易于解析的文本格式,并在Mathematica和其他需要使用的语言中编写自己的输入/输出函数。由于你正在处理的数据格式是固定的(始终有坐标三元组),最简单的解决方案可能是在导出之前将列表展平,并在导入后进行分区,如下所示:
Export["test.txt", Join @@@ a, "Table"]
b = Import["text.txt", "Table"]
Partition[#, 3]& /@ a

通过模仿Export["data.m", a, "Package"]的输出,我成功地做到了我想要的。谢谢! - Dror
@Dror,我想你也需要使用其他软件阅读数据文件。如果不是这种情况,而你只需要暂时存储/保存数据,那么“WDX”格式可能比“Package”更快速地进行导入/导出。但是,它是二进制的,所以你无法用文本编辑器检查它或将其导入其他程序。 “WDX”还可以存储任何类型的Mathematica表达式(我想)。 - Szabolcs

2

对于存储MMA表达式,我建议使用DumpSave(二进制,系统相关),SavePut,但如果您想使用Export,则应将a转换为字符串,并将其导出为文本。(我在下面使用ImportStringExpertString,所以我不需要文件,但是对于ImportExport也是同样的)。在我看来,这很牢固。

a = {{{0, 0, 0}, {1, 0, 0}, {1, 1, 0}}, {{0, 0, 1}, {1, 0, 1}, {1, 1, 1}}};
b = ToExpression@ImportString[ExportString[a // ToString, "Text"], "Text"]

(*  ==>
{{{0, 0, 0}, {1, 0, 0}, {1, 1, 0}}, {{0, 0, 1}, {1, 0, 1}, {1, 1, 1}}}
*)

a == b

(* ==> True *)

阅读您的多边形列表应该是相同的:

b = ToExpression@ImportString["test.dat", "Text"]

这与导出为“Package”有何不同?实际上,我刚刚发现可以导出为“Package”格式(.m文件),但它似乎做的事情差不多。 - Szabolcs
1
@Szabolcs,我之前完全不知道有导出到包选项的功能。现在我已经研究了这个功能,我认为“Package”是最好的选择(如果你不介意文件开头的Wolfram注释)。例如,如果你导出实数,“Text”选项会导出6位数字格式,而“Package”则使用完整精度。 - Sjoerd C. de Vries

1

你也可以做例如:

a={{{0,0,0},{1,0,0},{1,1,0}},{{0,0,1},{1,0,1},{1,1,1}}};

Export["c:\\test.dat",a,"MathML"];
b=ToExpression@Import["c:\\test.dat","MathML"]

(*
->{{{0, 0, 0}, {1, 0, 0}, {1, 1, 0}}, {{0, 0, 1}, {1, 0, 1}, {1, 1, 1}}}
*)

另一个好处是,这种方法不需要解析Import输出


虽然这对特定示例有效,但我觉得它看起来很不专业且易碎。其基本原理是构建一个 MathML 表达式,在呈现时看起来与 Mathematica 表达式差不多,然后重新导入它。人们只能希望重新导入的版本相同...如果我们采用这种方法,最好使用非易碎格式,例如仅使用表达式的 InputForm(这就是导出到“Package”格式所做的)。据我所知,“MathML”没有优于此的优势,只有劣势。 - Szabolcs
@Szabolcs 由于问题范围是“从txt文件导入数据到Mathematica”,我认为这种方法是合适和有效的。OP并不处理“表达式”,而只是按列表结构处理“数据”。 - Dr. belisarius
1
然而,MathML旨在交换和格式化数学表达式,而不是列表或数组。这种情况下它能够正常工作可能被视为意外...您认为为什么MathML比其他人类可读的表示数组的方式(如InputForm(“Package”),ExpressionML等)更好? - Szabolcs
1
@Szabolcs 我并没有说“更好”。它只是有效。但是(在我看来)比先加入导出再分区导入要好。 - Dr. belisarius

1

我也遇到了这个问题。我的解决方案如下:

IN[]: a = {{{0, 0, 0}, {1, 0, 0}, {1, 1, 0}}, {{0, 0, 1}, {1, 0, 1}, {1, 1, 1}}};
      Export["test.dat", a, "List"];
      b = ToExpression@Import["test.dat", "List"];
      a == b

Out[]: True

希望这能有所帮助。最好的问候。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接