使用Mathematica将列表创建为矩阵

3
我有一个问题需要用Mathematica解决。 我有一个带有位置测量的x和y坐标列表(以及在每个点处测量的数量的z值)。 所以,我的列表从list={{-762.369,109.998,0.915951},{-772.412,109.993,0.923894},{-777.39, 109.998, 0.918108},...}(x,y,z)开始。由于某些原因,我必须将所有这些x,y和z值填充到矩阵中。 如果每个y坐标有相同数量的x坐标(假设为80),那么这将很容易,然后我可以使用Partition[list,80],它会生成具有80列的矩阵(以及一些行,其数量由具有相同值的y坐标的数量确定)。不幸的是,情况并不那么简单,每个y的x坐标数量不是严格恒定的,如附加的ListPlot所示。 有人能给我一些建议,我该如何将该图的每个点/我的列表的每个x-y-(和z-)坐标填充到矩阵中吗?
为了更好地解释我想要的内容,我在附图中标示了一个矩阵。可以看到,我的绘图几乎每个点都会落入矩阵的一个单元格中,只有一些单元格是空的。 在绘图中,我使用红色来表示x坐标按顺序递增的点,蓝色表示x坐标按顺序递减的点(位置沿着一个弯曲线测量)。也许这种排序方式对解决问题有用... 这里 是我的坐标链接,也许这可以帮助解决问题。
好的,我希望我已经足够清楚地解释了我的问题。非常感谢您的帮助!

1
你想对你的矩阵做什么? - Dr. belisarius
@Szabolcs 非常感谢您的电子邮件回复和您在这里的答案!您的建议非常好!睡了几个小时后,我会尽力更好地理解它;-) 还要感谢您上传的提示。我不知道这个页面。我再次编辑了我的问题,并提供了一个包含我的x和y坐标的文件链接。因此,其他用户可以在需要尝试应用您或其他人的建议时使用它们。 - partial81
@belisarius 首先,我想找到一种通用的方法来解决我的问题(只需将坐标填入矩阵中)。其次,如果我的矩阵/张量的每个单元格都有x、y、z值,则可以使用ReliefImage或MatrixPlot绘制我的z值,而不再使用ListDensityPlot(据我所知,使用ListDensityPlot会在网格上插值我的z值。这是我不想一直拥有的东西)。第三,我有时对我的数据/图中的特定感兴趣区域感兴趣。由于论坛用户的大力帮助,如果我能生成ReliefImage,我就可以轻松地提取它们。 - partial81
如果你的目标只是得到一个z值的网格,那么这就是为了那个而做的很多工作……为什么不在{x,y,z}数据上使用Interpolation,然后使用生成的插值函数生成矩阵?您将能够使用ReliefImage或任何类似的功能绘制它。有什么好理由排除任何类型的插值吗?由于晶格不是完全正方形,因此我下面的答案也引入了扭曲。 - Szabolcs
@Szabolcs 好的,这是一个好问题。首先,我对是否存在一般解决方案感兴趣。其次,正如我在电子邮件中所述,我试图找到一种简单的方法从我的列表中提取我感兴趣的特定区域内的真实值(因为由于某些物理原因,有时我只能使用它们)。因此,我仍然认为/希望我的问题是有用的,尽管这对您来说是非常繁重的工作。也许其他人将来也可以从我们的答案中受益,并像我一样欣赏您的工作。 - partial81
显示剩余4条评论
1个回答

6
这个解决方案的基本思路是:
  • 所有点似乎都位于一个格子上,但它并不是一个精确的正方形格子(它是倾斜的)
  • 因此,让我们找到该格子的基向量,然后所有(大多数?)点将近似为基向量的整数线性组合
  • 沿着基向量的整数“坐标”将是 OP 矩阵的矩阵索引

(OP 向我发送了数据文件,其中包含 {x,y} 点坐标。)

读取数据:

data = Import["xy.txt", "Table"];

找到每个点最近的四个点,并注意它们水平和垂直方向上的距离大约为5:

nf = Nearest[data];

In:= # - data[[100]] & /@ nf[data[[100]], 5]

Out= {{0., 0.}, {-4.995, 0.}, {5.003, 0.001}, {-0.021, 5.003}, {0.204, -4.999}}

ListPlot[nf[data[[100]], 5], PlotStyle -> Red, 
  PlotMarkers -> Automatic, AspectRatio -> Automatic]

生成相邻点之间的差异向量,仅保留长度约为5的向量。
vv = Select[
      Join @@ Table[(# - data[[k]] & /@ nf[data[[k]], 5]), {k, 1, Length[data]}], 
      4.9 < Norm[#] < 5.1 &
     ];

把向量沿着它们可以指向的方向平均化,并保留两个“好”的向量(指向“上”或“右”)。
In:= Mean /@ GatherBy[vv, Round[ArcTan @@ #, 0.25] &]

Out= {{0.0701994, -4.99814}, {-5.00094, 0.000923234}, {5.00061, -4.51807*10^-6},  
      {-4.99907, -0.004153}, {-0.0667469, 4.9983}, {-0.29147, 4.98216}}

In:= {u1, u2} = %[[{3, 5}]]

Out= {{5.00061, -4.51807*10^-6}, {-0.0667469, 4.9983}}

使用一个随机点作为起点,这样基向量u1u2上的坐标将是整数:

translatedData = data[[100]] - # & /@ data;

让我们找到整数坐标并看看它们有多好(距离实际整数有多远):

In:= integerIndices = LinearSolve[Transpose[{u1, u2}], #] & /@ translatedData ;

In:= Max[Abs[integerIndices - Round[integerIndices]]]

Out= 0.104237

In:= ListPlot[{integerIndices, Round[integerIndices]}, PlotStyle -> {Black, Red}]

图片描述

所有点都接近于整数近似值。

将整数坐标偏移,使它们都为正,可以用作矩阵索引,然后将元素收集到矩阵中。我将坐标放在一个point对象中,以免混淆SparseArray

offset = Min /@ Transpose[Round[integerIndices]]
offset = {1, 1} - offset

result = 
 SparseArray[
  Thread[(# + offset & /@ Round[integerIndices]) -> point @@@ data]]

result = Normal[result] /. {point -> List, 0 -> Null}

最终,我们得到了一个矩阵result,每个元素是一个坐标对!(这里我用0 -> Null表示缺失的元素,这样做有些马虎:重要的是data中没有确切的0。)

MatrixForm[result[[1 ;; 10, 1 ;; 5]]]

enter image description here

编辑

只是为了好玩,让我们来看一下点的偏差,它们偏离了精确的整数格点:

lattice = #1 u1 + #2 u2 & @@@ Round[integerIndices];

delta = translatedData - lattice;
delta = # - Mean[delta] & /@ delta;

ListVectorPlot[Transpose[{lattice, delta}, {2, 1, 3}], VectorPoints -> 30]

enter image description here


使用基向量的想法很好。如果在稀疏数组中不使用带有数据的点,会出现什么问题?(我正在iPad上写作,所以无法尝试Mathematica) - acl
@acl,我没有花时间去弄清楚它的工作原理...我之前知道的是可以用SparseArray[{ {row, column} -> element }]创建一个(稀疏)数组。如果element是一个ListSparseArray会给我一个1D数组。我猜这是因为SparseArray[{index, index, ...} -> {element, element, ...}]也是一种有效的语法。 - Szabolcs
@Sza 好奇!我在这里做了几乎相同的事情 https://dev59.com/O2445IYBdhLWcg3wUoxe#4917954 - Dr. belisarius
@Szabolcs 感谢您的解决方案和解释。它们真的很好!只是对于我来说,由于您的代码远超出了我的编程技能,有些细节有点难以理解。但无论如何,我已经理解了大部分的解决方案!而且似乎我可以很好地将您的解决方案适应到我的实际数据中。再次感谢您! - partial81

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