mydata.d
我想要绘制图表的文件中有一些如下数据(第一列和第二列) :
8 98826 year 2008
9 104925 year 2009
10 140153 year 2010
11 178414 year 2011
由于第二个数字很大,我使用了宏sarith
。这是我的绘图元帖子代码:
input graph
input sarith
beginfig(1);
draw begingraph(8cm,5cm);
setrange(8,whatever,12,whatever);
gdraw "mydata.d" withpen pencircle scaled 1.5pt;;
gdraw "mydata.d" plot btex $\bullet$ etex;
autogrid(otick.bot,);
gdotlabel.lrt(btex $98\;826$ etex, 8,"98826");
gdotlabel.lrt(btex $104\;925$ etex, 9,"104925");
gdotlabel.lrt(btex $140\;153$ etex, 10,"140153");
gdotlabel.lrt(btex $178\;414$ etex, 11,"178414");
endgraph;
endfig;
end
因此,我绘制了前两列,去掉了 y 轴刻度和标签,并在图中的每个坐标处写入了 y 值。我有以下问题:
我想显示年份,即 2008 年至 2010 年,但 metapost 仅在 x 轴上显示 2010 年,这就是为什么我选择数字 8 到 10。这是为什么?
如果绘制曲线,您将在每个坐标处看到两个点,其中写有相应的 y 值。为什么会发生这种情况?即使我删除行 gdraw ,也会出现这种情况
mydata.d" plot btex $\bullet$ etex
。在行中gdotlabel
,我必须将第二列中的数字括在引号中,例如“98826”。这是否会导致 metapost 在如此大的数字下无法准确显示,从而出现两个点?如果从 1 开始我们可以很好地显示 2008、2009、2010 和 2011 年,那么我们如何显示它们,但要逆时针旋转 90 度,以便标签不会在水平方向上占用太多空间?
如果我要求 metapost 在 y 轴上显示 y 值,那么它将以指数形式而不是纯十进制形式(如 100000、150000 等)显示。如何实现这一点?
我知道 metapost 会忽略除这两列之外的其他列,这对于在第一行写与该行相关的注释(例如 2008 年)很有用。但是,如果我想为整个文件添加全局注释(例如“我每年吃的苹果数量”),那么我无法在文件的开头执行此操作。我假设我们可以在文件末尾执行此操作,但是怎么做呢?我尝试过留空并以 % 符号开始注释行,但这样做不起作用。
我在 Win XP 下使用 TeXLive 2010 和 MetaPost,版本 1.211。我也尝试过 TL 2011 和 MetaPost 1.504。
非常感谢您的帮助...
答案1
我知道这已经过时了,但这些问题的答案相当简单,所以我想我会试一试。尽管我是 MP 的粉丝,但我认为我会同意 @percusse 的观点,即 pgfplots 可能比input graph
MP 更好。
我马上就会列出问题清单,但首先我们可以简化一下。MP 图表输入的正确格式如下:
2008 98826 Your comments go here
2009 104925
2010 140153
2011 178414
所以我假设你已经改为mydata.d
这种格式。
有了这个数据文件,我们就可以生成仅用一条线的图表gdraw
。
prologues := 3;
outputtemplate := "%j%c.eps";
input graph
beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" withpen pencircle scaled 1/2 withcolor 2/3 red;
endgraph;
endfig;
end.
我添加了一些选项,使线条变成红色,并具有合适的粗细。结果如下:
我们马上就发现了第一个问题,所有年份都被打印成了“2010”。仔细阅读手册后,我们发现这是因为所有数字标签的默认精度都是 3 位有效数字。因此所有年份都被四舍五入到最接近的 10 位。
执行此操作的命令是默认autogrid
由命令添加的隐式命令endgraph
。为了解决这个问题,我们必须半手动地格式化标签,如第 2.2 节末尾所述手册像这样更改我们的源代码:
prologues := 3;
outputtemplate := "%j%c.eps";
input graph
beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" withpen pencircle scaled 1/2 withcolor 2/3 red;
for x=auto.x: otick.bot(format("%4g", x), x); endfor
for y=auto.y: otick.lft(format("%g", y), y); endfor
endgraph;
endfig;
end.
产生更好的结果。我们在这里所做的是将年份四舍五入为 4 位有效数字。
第二个问题是将点标记整齐地放在每个数据点上。正确的方法是将选项添加plot
到gdraw
命令中。OP 的问题是使用plot btex $\bullet$ etex
将点放在了错误的位置。手册也解释了这一点,但不是很清楚。我的建议是你在 MP 中制作自己的点标记,如下所示:
prologues := 3;
outputtemplate := "%j%c.eps";
input graph
picture bullet; bullet = image(drawdot origin withpen pencircle scaled 2);
beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" plot bullet withpen pencircle scaled 1/2 withcolor 2/3 red;
for x=auto.x: otick.bot(format("%4g", x), x); endfor
for y=auto.y: otick.lft(format("%g", y), y); endfor
endgraph;
endfig;
end.
生成如下内容:
第三个问题是“如何旋转年份标签”?为此,我们需要提供一个函数来代替该format
函数。输出应该是一个picture
对象。以下是其中一种方法:
prologues := 3;
outputtemplate := "%j%c.eps";
input graph
picture bullet; bullet = image(drawdot origin withpen pencircle scaled 2);
vardef year_label(expr Y) = decimal Y infont "cmr10" rotated 60 enddef;
beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" plot bullet withpen pencircle scaled 1/2 withcolor 2/3 red;
for x=auto.x: otick.bot(year_label(x), x); endfor
for y=auto.y: otick.lft(format("%g", y), y); endfor
endgraph;
endfig;
end.
现在图表看起来是这样的。如果你真的想要 90° 的话,你可以调整一下旋转角度。
第四个问题是关于是-轴标签。这里的问题也与舍入有关,但我们不能像更改年份那样更改精度,因为绝对值大于 4096,所以graph
会自动使用 MP 的字符串算法,因此格式规则略有不同(在我看来不是很好)。如果您真的想要很多零,那么我建议的最好方法是我们“手动”输入标签:
prologues := 3;
outputtemplate := "%j%c.eps";
input graph
picture bullet; bullet = image(drawdot origin withpen pencircle scaled 2);
vardef year_label(expr Y) = decimal Y infont "cmr10" rotated 60 enddef;
beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" plot bullet withpen pencircle scaled 1/2 withcolor 2/3 red;
for x=auto.x: otick.bot(year_label(x), x); endfor
otick.lft("100,000" infont "cmr10", "100000");
otick.lft("140,000" infont "cmr10", "140000");
otick.lft("180,000" infont "cmr10", "180000");
endgraph;
endfig;
end.
生成如下内容:
但明显的缺点是,你必须知道数据范围才能将标签放在正确的位置。所以我认为我最后的努力是通过转换它们来减小 y 值的大小,并在轴上添加一个刻度标签:
prologues := 3;
outputtemplate := "%j%c.eps";
input graph
input sarith
picture bullet; bullet = image(drawdot origin withpen pencircle scaled 2);
vardef year_label(expr Y) = decimal Y infont "cmr10" rotated 60 enddef;
beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" plot bullet withpen pencircle scaled 1/2 withcolor 2/3 red;
for x=auto.x: otick.bot(year_label(x), x); endfor
for y=auto.y: otick.lft(format("%g", y Sdiv "1000"), y); endfor
glabel.lft("Thousands" infont "cmr8" rotated 90, OUT);
endgraph;
endfig;
end.
就像这样:
第五个问题关于将全局注释放在顶部和底部的答案是“不要这样做”。将全局注释放在前几列的右侧。
你能在每个数据集结束的空白行后添加注释,但请注意,如果您多次阅读该文件(如 OP 所做的那样),那么您的注释可能会被误认为是第二个数据集。所以我建议您不要这样做。
答案2
我强烈建议使用pgfplots
对于此类图。下面是包括数据注释、年份处理千位分隔等的示例:
\documentclass{article}
\usepackage{pgfplots}
\pgfplotstableread[skip first n = 4]{%
% Some TeX comment
Comment line
The number days that the doctor
will be kept away...
Comment end
year n
2008 98826
2009 104925
2010 140153
2011 178414
}\mytable
\begin{document}
\begin{tikzpicture}
\begin{axis}[scaled ticks=false,
xtick=data,
xticklabel={\pgfmathprintnumber[fixed,1000 sep=]{\tick}},
xticklabel style={rotate=90},
yticklabel={\pgfmathprintnumber[int detect,fixed,1000 sep={\;}]{\tick}}
]
\addplot table[x=year,y=n]{\mytable};
\end{axis}
\end{tikzpicture}
\end{document}