我想使用网格线在2d图上创建millimeter graphing paper的效果,以显示多变量函数如何依赖于1变量。不同变量的尺度差异很大,所以我的天真方法(我之前使用过)似乎不起作用。
目前的例子:
<< ErrorBarPlots`
Cmb[x_, y_, ex_, ey_] := {{N[x], N[y]}, ErrorBar[ex, ey]};
SetAttributes[Cmb, Listable];
ELP[x_, y_, ex_, ey_, name_] :=
ErrorListPlot[
Cmb[x, y, ex, ey],
PlotRange -> FromTo[x, y],
PlotLabel -> name,
Joined -> True, Frame -> True, GridLines -> GetGrid,
ImageSize -> {600}
]
两个FromTo
(我想在框架中留下5%的边距)而GetGrid
不能完全按照我的要求工作。
在某些轴上,变量与10的许多阶数不同。我不希望,一个轴比其他轴具有多个10个网格线的订单。最重要的是,我希望网格线与刻度线对齐。
示例数据:
ELP[
{4124961/25000000, 27573001/100000000, 9162729/25000000, 44635761/
100000000, 15737089/25000000, 829921/1562500, 4405801/4000000,
23068809/25000000, 329386201/100000000, 58079641/100000000},
{1/10, 1/5, 3/10, 2/5, 3/5, 1/2, 1/2, 1/2, 1/2, 1/2},
{2031/(250000 Sqrt[10]), 5251/(500000 Sqrt[10]), 3027/(
250000 Sqrt[10]), 6681/(500000 Sqrt[10]), 3967/(250000 Sqrt[10]),
911/(62500 Sqrt[10]), 2099/(100000 Sqrt[10]), 4803/(
250000 Sqrt[10]), 18149/(500000 Sqrt[10]), 7621/(500000 Sqrt[10])},
{1/2000, 1/1000, 3/2000, 1/500, 3/1000, 1/400, 1/400, 1/400, 1/400,
1/400},
"T2, m"
]
会导致:
我天真的GetGrid,在某种程度上有效:
FromTo[x_, y_] := Module[{dx, dy},
dx = (Max[x] - Min[x])*0.1;
dy = (Max[y] - Min[y])*0.1;
{{Min[x] - dx, Max[x] + dx}, {Min[y] - dy, Max[y] + dy}}];
GetGrid[min_, max_] := Module[{step, i},
step = (max - min)/100;
Table[
{min + i*step,
If[Equal[Mod[i, 10], 0],
Directive[Gray, Thick, Opacity[0.5]],
If[Equal[Mod[i, 5], 0],
Directive[Gray, Opacity[0.5]],
Directive[LightGray, Opacity[0.5]]
]]},
{i, 1, 100}]
]
如何使GridLines与ticks对齐?
编辑:使用
GetTicks[x_, y_] := Module[{dx, dy},
dx = (Max[x] - Min[x])*0.1;
dy = (Max[y] - Min[y])*0.1;
{
Min[x] - dx + Table[i*dx*1.2, {i, 1, 9}],
Min[y] - dy + Table[i*dy*1.2, {i, 1, 9}]
}];
ELP[x_, y_, ex_, ey_, name_] :=
ErrorListPlot[
Cmb[x, y, ex, ey],
PlotRange -> FromTo[x, y],
PlotLabel -> name,
Joined -> True, Frame -> True, GridLines -> GetGrid,
FrameTicks -> GetTicks[x, y],
ImageSize -> {600},
AspectRatio -> 1
]
我可以得到:
这样做要好得多。但我想转移网格而不是刻度。
编辑:@Sjoerd C. de Vries
您的解决方案可以保存我想存档和运行的内容。我还注意到,如果我采用样本数据的前5个元素,那么绘图将是(元素被排序并且回归线被添加)。
请注意,最左边的元素就像离网格一样。
答案 0 :(得分:8)
不要使用FrameTicks,而是正确移动网格。这是第一种方法。晚餐等待。
getGrid[min_, max_] :=
Module[{step, i},
Print[{min, max}];
step = 1/100;
Table[
{
Floor[min, 0.1] + i*step,
If[Equal[Mod[i, 10], 0], Directive[Gray, Thick, Opacity[0.5]],
If[Equal[Mod[i, 5], 0], Directive[Gray, Opacity[0.5]],
Directive[LightGray, Opacity[0.5]]
]
]
},
{i, 1, (Ceiling[max, 0.1] - Floor[min, 0.1])/step // Round}
]
]
使用适合网格的AspectRatio(可能是x和y范围的比率)
晚餐后更新
为了使其针对不同的价值范围(根据您的评论)更加健壮,我会生成由ListPlot
选择并在此基础上执行的刻度:
getGrid[min_, max_] :=
Module[{step, i,j},
i = Cases[(Ticks /.
AbsoluteOptions[ListPlot[{{min, min}, {max, max}}],
Ticks])[[1]], {a_, ___, {_, AbsoluteThickness[0.25`]}} :> a];
step = i[[2]] - i[[1]];
Table[
{
i[[1]] + j*step/10,
If[Equal[Mod[j, 10], 0], Directive[Gray, Thick, Opacity[0.5]],
If[Equal[Mod[j, 5], 0], Directive[Gray, Opacity[0.5]],
Directive[LightGray, Opacity[0.5]]
]
]
},
{j, 0, 10 Length[i]}
]
]
获得产生方形栅格的宽高比
getAspect[{{minX_, maxX_}, {minY_, maxY_}}] :=
Module[{stepx, stepy, i, rx, ry},
i = (Ticks /.AbsoluteOptions[ListPlot[{{minX, minY}, {maxX, maxY}}], Ticks]);
rx = Cases[i[[1]], {a_, ___, {_, AbsoluteThickness[0.25`]}} :> a];
stepx = rx[[2]] - rx[[1]];
ry = Cases[i[[2]], {a_, ___, {_, AbsoluteThickness[0.25`]}} :> a];
stepy = ry[[2]] - ry[[1]];
((maxY - minY)/stepy)/((maxX - minX)/stepx)
]
测试
ELP[x_, y_, ex_, ey_, name_] :=
ErrorListPlot[Cmb[x, y, ex, ey], PlotLabel -> name, Joined -> True,
Frame -> True, GridLines -> getGrid, ImageSize -> {600},
PlotRangePadding -> 0, AspectRatio -> getAspect[FromTo[x, y]],
PlotRange -> FromTo[x, y]]
ELP[{4124961/25000000, 27573001/100000000, 9162729/25000000,
44635761/100000000, 15737089/25000000, 829921/1562500,
4405801/4000000, 23068809/25000000, 329386201/100000000,
58079641/100000000}, {1/10, 1/5, 3/10, 2/5, 3/5, 1/2, 1/2, 1/2, 1/2,
1/2}, {2031/(250000 Sqrt[10]), 5251/(500000 Sqrt[10]),
3027/(250000 Sqrt[10]), 1/100000 6681/(500000 Sqrt[10]),
3967/(250000 Sqrt[10]), 911/(62500 Sqrt[10]),
2099/(100000 Sqrt[10]), 4803/(250000 Sqrt[10]),
18149/(500000 Sqrt[10]), 7621/(500000 Sqrt[10])}, {1/2000, 1/1000,
3/2000, 1/500, 3/1000, 1/400, 1/400, 1/400, 1/400, 1/400}, "T2, m"]
这里我将y值除以20并将x值乘以10000以显示网格仍然良好:
最终更新(我希望)
这将FindDivisions用作suggested by belisarius。但是,我按照Margus的要求使用了毫米纸的三级线结构标准:
getGrid[x_, y_] :=
FindDivisions[{x, y}, {10, 2, 5}] /. {r_, s_, t_} :>
Join[
{#, Directive[Gray, Thick, Opacity[0.5]]} & /@ r,
{#, Directive[Gray, Opacity[0.5]]} & /@ Union[Flatten[s]],
{#, Directive[LightGray, Opacity[0.5]]} & /@ Union[Flatten[t]]
]
和
getAspect[{{minX_, maxX_}, {minY_, maxY_}}] :=
Module[{stepx, stepy},
stepx = (#[[2]] - #[[1]]) &@FindDivisions[{minX, maxX}, 10];
stepy = (#[[2]] - #[[1]]) &@FindDivisions[{minY, maxY}, 10];
((maxY - minY)/stepy)/((maxX - minX)/stepx)
]
警告!!! 强>
我刚注意到如果你在MMA中有这个:
然后你把它复制到SO(只是ctrl-c ctrl-v),你得到这个:
(maxY - minY)/stepy/(maxX - minX)/stepx
在数学上不等同。它应该是这样的:
((maxY - minY)*stepx)/((maxX - minX)*stepy)
我在上面的代码中对此进行了更正,但在我的计算机上正常工作时,它已被错误地发布了半天。认为最好提一下这个。
答案 1 :(得分:4)
我认为 FindDivisions [] 就是你所追求的:
FindDivisions [{XMIN,XMAX},n]的 找到一个关于n个“漂亮”数字的列表,它将xmin到xmax的间隔分成等间距的部分。
getTicks[x_, y_] := Flatten@FindDivisions[#, {10}] & /@ FromTo[x, y]
getGrid [x_,y_] := FindDivisions[{x,y},{10,5}]/.
{r__,{s__}}:>Join@@{s,{#,{Gray,Thick}}&/@r}
答案 2 :(得分:1)
如果您对FrameTicks
和Gridlines
使用相同的功能,它们会排成一行。
请参阅FrameTicks和GridLines。我认为边境需要ImageMargins
。