如何调整 的位置y unit
?pgfplots
我试图将其放在图形框的左上角附近。但是,可能(但不必)是科学乘数。如下面的专业排版图片所示,单位应显示在乘数之后,当然应与乘数对齐,就像写成一个整体一样:$10^3$[m]
。如果y
轴上的值较小且未显示指数符号,[m]
则单位仍应呈现在左上角上方,但最好靠近左边缘。
我知道[m]
图片中的单位是与y
轴标签一起绘制的。我不需要将整数放在y label
乘数附近,而只需放置单位即可。事实上,我根本不需要轴标签。是否可以控制科学乘数的格式并附加单位?
我不确定这是否重要,但为了完整起见,让我补充一下,我已经结合了 Jake 的刻度缩放解决方案这里只有指数,即 3 的倍数。
MWE 提供:
\documentclass{minimal}
\usepackage{pgfplots}
\usepgfplotslibrary{units}
\makeatletter
\newif\ifpgfplots@scaled@x@ticks@engineering
\pgfplots@scaled@x@ticks@engineeringfalse
\newif\ifpgfplots@scaled@y@ticks@engineering
\pgfplots@scaled@y@ticks@engineeringfalse
\newif\ifpgfplots@scaled@z@ticks@engineering
\pgfplots@scaled@z@ticks@engineeringfalse
\pgfplotsset{
scaled x ticks/engineering/.code=
\pgfplots@scaled@x@ticks@engineeringtrue,
scaled y ticks/engineering/.code=
\pgfplots@scaled@y@ticks@engineeringtrue,
scaled z ticks/engineering/.code=
\pgfplots@scaled@y@ticks@engineeringtrue,
% scaled ticks=engineering % Uncomment this line if you want "engineering" to be on by default
}
\def\pgfplots@init@scaled@tick@for#1{%
\global\def\pgfplots@glob@TMPa{0}%
\expandafter\pgfplotslistcheckempty\csname pgfplots@prepared@tick@positions@major@#1\endcsname
\ifpgfplotslistempty
% we have no tick labels. Omit the tick scale label as well!
\else
\begingroup
\ifcase\csname pgfplots@scaled@ticks@#1@choice\endcsname\relax
% CASE 0 : scaled #1 ticks=false: do nothing here.
\or
% CASE 1 : scaled #1 ticks=true:
%--------------------------------
% the \pgfplots@xmin@unscaled@as@float is set just before the data
% scale transformation is initialised.
%
% The variables are empty if there is no datascale transformation.
\expandafter\let\expandafter\pgfplots@cur@min@unscaled\csname pgfplots@#1min@unscaled@as@float\endcsname
\expandafter\let\expandafter\pgfplots@cur@max@unscaled\csname pgfplots@#1max@unscaled@as@float\endcsname
%
\ifx\pgfplots@cur@min@unscaled\pgfutil@empty
\edef\pgfplots@loc@TMPa{\csname pgfplots@#1min\endcsname}%
\expandafter\pgfmathfloatparsenumber\expandafter{\pgfplots@loc@TMPa}%
\let\pgfplots@cur@min@unscaled=\pgfmathresult
\edef\pgfplots@loc@TMPa{\csname pgfplots@#1max\endcsname}%
\expandafter\pgfmathfloatparsenumber\expandafter{\pgfplots@loc@TMPa}%
\let\pgfplots@cur@max@unscaled=\pgfmathresult
\fi
%
\expandafter\pgfmathfloat@decompose@E\pgfplots@cur@min@unscaled\relax\pgfmathfloat@a@E
\expandafter\pgfmathfloat@decompose@E\pgfplots@cur@max@unscaled\relax\pgfmathfloat@b@E
\pgfplots@init@scaled@tick@normalize@exponents
\ifnum\pgfmathfloat@b@E<\pgfmathfloat@a@E
\pgfmathfloat@b@E=\pgfmathfloat@a@E
\fi
\xdef\pgfplots@glob@TMPa{\pgfplots@scale@ticks@above@exponent}%
\ifnum\pgfplots@glob@TMPa<\pgfmathfloat@b@E
% ok, scale it:
\expandafter\ifx % Check whether we're using engineering notation (restricting exponents to multiples of three)
\csname ifpgfplots@scaled@#1@ticks@engineering\expandafter\endcsname
\csname iftrue\endcsname
\divide\pgfmathfloat@b@E by 3
\multiply\pgfmathfloat@b@E by 3
\fi
\multiply\pgfmathfloat@b@E by-1
\xdef\pgfplots@glob@TMPa{\the\pgfmathfloat@b@E}%
\else
\xdef\pgfplots@glob@TMPa{\pgfplots@scale@ticks@below@exponent}%
\ifnum\pgfplots@glob@TMPa>\pgfmathfloat@b@E
% ok, scale it:
\expandafter\ifx % Check whether we're using engineering notation (restricting exponents to multiples of three)
\csname ifpgfplots@scaled@#1@ticks@engineering\expandafter\endcsname
\csname iftrue\endcsname
\advance\pgfmathfloat@b@E by -2
\divide\pgfmathfloat@b@E by 3
\multiply\pgfmathfloat@b@E by 3
\fi
\multiply\pgfmathfloat@b@E by-1
\xdef\pgfplots@glob@TMPa{\the\pgfmathfloat@b@E}%
\else
% no scaling necessary:
\xdef\pgfplots@glob@TMPa{0}%
\fi
\fi
\or
% CASE 2 : scaled #1 ticks=base 10:
%--------------------------------
\c@pgf@counta=\csname pgfplots@scaled@ticks@#1@arg\endcsname\relax
%\multiply\c@pgf@counta by-1
\xdef\pgfplots@glob@TMPa{\the\c@pgf@counta}%
\or
% CASE 3 : scaled #1 ticks=real:
%--------------------------------
\pgfmathfloatparsenumber{\csname pgfplots@scaled@ticks@#1@arg\endcsname}%
\global\let\pgfplots@glob@TMPa=\pgfmathresult
\or
% CASE 4 : scaled #1 ticks=manual:
\expandafter\global\expandafter\let\expandafter\pgfplots@glob@TMPa\csname pgfplots@scaled@ticks@#1@arg\endcsname
\fi
\endgroup
\fi
\expandafter\let\csname pgfplots@tick@scale@#1\endcsname=\pgfplots@glob@TMPa%
}
\makeatother
\begin{document}
\begin{tikzpicture}
\begin{axis}[scaled ticks=engineering, y unit=m,height=4cm]
\addplot [domain=0:1] {10000*\x};
\end{axis}
\end{tikzpicture}
The multiplier should be printed as $\cdot10^3$[m] instead of merely $\cdot10^3$.
\end{document}
答案1
这是一种不使用units
库的方法,而是定义一个新键y unit label=<text>
,将其放置<text>
在刻度标签后面(如果存在)或刻度标签的位置(如果不存在)。
如果您将以下代码放在序言中...
\makeatletter
\long\def\ifnodedefined#1#2#3{%
\@ifundefined{pgf@sh@ns@#1}{#3}{#2}%
}
\pgfplotsset{
y unit label/.style={
y tick scale label style={
name=y tick scale label,
inner xsep=0pt
},
after end axis/.append code={
\ifnodedefined{y tick scale label}{%
\tikzset{
every y unit label/.append style={
anchor=base west, at=(y tick scale label.base east)
}
}
}{%
\tikzset{
every y unit label/.append style={
/pgfplots/every y tick scale label
}
}
}
\node [every y unit label] {#1};
}
}
}
\makeatother
...您可以编写以下内容...
\begin{axis}[
scaled ticks=engineering,
y unit label=m,
height=4cm,
]
\addplot [domain=0:1] {10000*\x};
\end{axis}
... 要得到 ...
... 或者 ...
\begin{axis}[
scaled ticks=engineering,
y unit label=m,
height=4cm,
]
\addplot [domain=0:1] {10000*\x};
\end{axis}
... 要得到 ...
完整代码:
\documentclass{article}
\usepackage{pgfplots}
\makeatletter
\newif\ifpgfplots@scaled@x@ticks@engineering
\pgfplots@scaled@x@ticks@engineeringfalse
\newif\ifpgfplots@scaled@y@ticks@engineering
\pgfplots@scaled@y@ticks@engineeringfalse
\newif\ifpgfplots@scaled@z@ticks@engineering
\pgfplots@scaled@z@ticks@engineeringfalse
\pgfplotsset{
scaled x ticks/engineering/.code=
\pgfplots@scaled@x@ticks@engineeringtrue,
scaled y ticks/engineering/.code=
\pgfplots@scaled@y@ticks@engineeringtrue,
scaled z ticks/engineering/.code=
\pgfplots@scaled@y@ticks@engineeringtrue,
% scaled ticks=engineering % Uncomment this line if you want "engineering" to be on by default
}
\def\pgfplots@init@scaled@tick@for#1{%
\global\def\pgfplots@glob@TMPa{0}%
\expandafter\pgfplotslistcheckempty\csname pgfplots@prepared@tick@positions@major@#1\endcsname
\ifpgfplotslistempty
% we have no tick labels. Omit the tick scale label as well!
\else
\begingroup
\ifcase\csname pgfplots@scaled@ticks@#1@choice\endcsname\relax
% CASE 0 : scaled #1 ticks=false: do nothing here.
\or
% CASE 1 : scaled #1 ticks=true:
%--------------------------------
% the \pgfplots@xmin@unscaled@as@float is set just before the data
% scale transformation is initialised.
%
% The variables are empty if there is no datascale transformation.
\expandafter\let\expandafter\pgfplots@cur@min@unscaled\csname pgfplots@#1min@unscaled@as@float\endcsname
\expandafter\let\expandafter\pgfplots@cur@max@unscaled\csname pgfplots@#1max@unscaled@as@float\endcsname
%
\ifx\pgfplots@cur@min@unscaled\pgfutil@empty
\edef\pgfplots@loc@TMPa{\csname pgfplots@#1min\endcsname}%
\expandafter\pgfmathfloatparsenumber\expandafter{\pgfplots@loc@TMPa}%
\let\pgfplots@cur@min@unscaled=\pgfmathresult
\edef\pgfplots@loc@TMPa{\csname pgfplots@#1max\endcsname}%
\expandafter\pgfmathfloatparsenumber\expandafter{\pgfplots@loc@TMPa}%
\let\pgfplots@cur@max@unscaled=\pgfmathresult
\fi
%
\expandafter\pgfmathfloat@decompose@E\pgfplots@cur@min@unscaled\relax\pgfmathfloat@a@E
\expandafter\pgfmathfloat@decompose@E\pgfplots@cur@max@unscaled\relax\pgfmathfloat@b@E
\pgfplots@init@scaled@tick@normalize@exponents
\ifnum\pgfmathfloat@b@E<\pgfmathfloat@a@E
\pgfmathfloat@b@E=\pgfmathfloat@a@E
\fi
\xdef\pgfplots@glob@TMPa{\pgfplots@scale@ticks@above@exponent}%
\ifnum\pgfplots@glob@TMPa<\pgfmathfloat@b@E
% ok, scale it:
\expandafter\ifx % Check whether we're using engineering notation (restricting exponents to multiples of three)
\csname ifpgfplots@scaled@#1@ticks@engineering\expandafter\endcsname
\csname iftrue\endcsname
\divide\pgfmathfloat@b@E by 3
\multiply\pgfmathfloat@b@E by 3
\fi
\multiply\pgfmathfloat@b@E by-1
\xdef\pgfplots@glob@TMPa{\the\pgfmathfloat@b@E}%
\else
\xdef\pgfplots@glob@TMPa{\pgfplots@scale@ticks@below@exponent}%
\ifnum\pgfplots@glob@TMPa>\pgfmathfloat@b@E
% ok, scale it:
\expandafter\ifx % Check whether we're using engineering notation (restricting exponents to multiples of three)
\csname ifpgfplots@scaled@#1@ticks@engineering\expandafter\endcsname
\csname iftrue\endcsname
\advance\pgfmathfloat@b@E by -2
\divide\pgfmathfloat@b@E by 3
\multiply\pgfmathfloat@b@E by 3
\fi
\multiply\pgfmathfloat@b@E by-1
\xdef\pgfplots@glob@TMPa{\the\pgfmathfloat@b@E}%
\else
% no scaling necessary:
\xdef\pgfplots@glob@TMPa{0}%
\fi
\fi
\or
% CASE 2 : scaled #1 ticks=base 10:
%--------------------------------
\c@pgf@counta=\csname pgfplots@scaled@ticks@#1@arg\endcsname\relax
%\multiply\c@pgf@counta by-1
\xdef\pgfplots@glob@TMPa{\the\c@pgf@counta}%
\or
% CASE 3 : scaled #1 ticks=real:
%--------------------------------
\pgfmathfloatparsenumber{\csname pgfplots@scaled@ticks@#1@arg\endcsname}%
\global\let\pgfplots@glob@TMPa=\pgfmathresult
\or
% CASE 4 : scaled #1 ticks=manual:
\expandafter\global\expandafter\let\expandafter\pgfplots@glob@TMPa\csname pgfplots@scaled@ticks@#1@arg\endcsname
\fi
\endgroup
\fi
\expandafter\let\csname pgfplots@tick@scale@#1\endcsname=\pgfplots@glob@TMPa%
}
\makeatother
\makeatletter
\long\def\ifnodedefined#1#2#3{%
\@ifundefined{pgf@sh@ns@#1}{#3}{#2}%
}
\pgfplotsset{
y unit label/.style={
y tick scale label style={
name=y tick scale label,
inner xsep=0pt
},
after end axis/.append code={
\ifnodedefined{y tick scale label}{%
\tikzset{
every y unit label/.append style={
anchor=base west, at=(y tick scale label.base east)
}
}
}{%
\tikzset{
every y unit label/.append style={
/pgfplots/every y tick scale label
}
}
}
\node [every y unit label] {#1};
}
}
}
\makeatother
\pgfplotsset{compat=1.8}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
scaled ticks=engineering,
y unit label=m,
height=4cm,
]
\addplot [domain=0:1] {10*\x};
\end{axis}
\end{tikzpicture}
\end{document}
答案2
这不是一种通用方法,而是在没有其他解决方案的情况下的权宜之计。在这种情况下,关闭 y 轴标签,并在指定位置用所需文本覆盖图像。与您的 MWE 相关的更改的相关行如下:
\usepackage{stackengine}
\def\stackalignment{l}
\begin{document}
\topinset{[m]}{%
\begin{tikzpicture}
\begin{axis}[scaled ticks=engineering, height=4cm]
\addplot [domain=0:1] {10000*\x};
\end{axis}
\end{tikzpicture}%
}{.03in}{.8in}