
我想用 來創建氣候記錄儀(氣候圖)pgfplots
,但是這些圖表對於軸縮放有一些特殊的規則(由 Walter 和 Lieth 大約 50 年前定義),我完全不知道如何用 來實現pgfplots
,因為第二個y軸允許在兩者之間改變縮放比例,並且兩個 y 軸的縮放比例相互耦合。下面的例子。
規則:如果不存在低於零度的溫度,則左側 y 軸(溫度 T)從零開始以 10°C 的步長縮放,否則它也會以低於零度的 10°C 的步長延伸。這仍然是簡單的部分(我可以做到),現在是困難的部分:右側 y 軸(雨量)以 T 值的兩倍縮放,最大可達 300mm。但如果有 300 毫米以上的降雨,則從 100 毫米開始以 200 毫米為步長進行縮放。右軸永遠不會低於零。
我的問題是:我必須使用哪些命令來根據輸入值動態更改軸縮放並將軸相互耦合?{x,y}{min,max}
,tick
朋友肯定是不夠的。我知道使用 pgfplots 繪圖的基礎知識,但我完全不知道從哪裡開始這種動態縮放方法,也不知道我必須自己計算多少(用自己的程式碼)以及pgfplots
能為我做多少。例如,我顯然需要以某種方式解析輸入資料以找到最大值,但我不知道如何在pgfplots
.
為了有一些東西可以使用,這裡是第一個範例的數據:
#bombay.txt
#M T/°C N/mm
1 23.9 3
2 23.9 3
3 26.1 3
4 28.1 2
5 29.7 18
6 28.9 485
7 27.2 617
8 27.0 340
9 27.0 264
10 28.1 64
11 27.2 13
12 25.6 3
這就是我如何獲得程式碼方面的知識,但現在我不知道如何繼續(顏色,線條樣式,網格等現在不重要,我只能自己做軸縮放/耦合是問題):
\documentclass{standalone}
\usepackage{pgfplots} \pgfplotsset{compat=newest}
\usepackage{siunitx}
\begin{document}
\begin{tikzpicture}
\def\filename{bombay.txt}
\def\monthnames{{"J","F","Mar","A","May","Jun","Jul","A","S","O","N","D"}}
\begin{axis}[
ylabel={Temperature in \si{\celsius}},
tick pos=left,
xticklabel={\pgfmathparse{\monthnames[Mod(\tick-1,12)]}\pgfmathresult},
xmin=1, xmax=12,
ymin=0, ytick={0,10,20,30,40,50}]
\addplot+[red, mark=none] table [x index=0, y index=1] {\filename};
\end{axis}
\begin{axis}[
ylabel={Rain in \si{\milli\metre}},
axis y line*=right,
hide x axis,
xmin=1, xmax=12, ymin=0]
\addplot+[blue, mark=none] table [x index=0, y index=2] {\filename};
\end{axis}
\end{tikzpicture}
\end{document}
例 1:雨軸縮放比例變化(因為 > 300mm),僅 T > 0
範例 2:雨軸不會改變縮放比例,因為它總是 < 300mm。 T<0。
答案1
您所需要的可以透過設定的樣式來實現
- 配置雨軸的非線性變換
- 計算兩個 y 軸的合適(耦合)軸限制
- 計算兩個 y 軸的合適(耦合)單位
- 需要手動輸入來決定兩個軸的起點/終點。根據我從您的用例中了解到的情況,該輸入由最低溫度和最大降雨量組成(另一個限制始終是隱式綁定的)。
我得到了以下高級原型:
\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}
% The following \pgfplotsset macro defines a *manual* wheather
% visualization system which couples temperature and rain axis.
\pgfplotsset{
rain trafo/.style={
y coord trafo/.code={%
\pgfmathparse{##1 > 100 ? 100 + 0.1*(##1 - 100) : ##1}%
},%
y coord inv trafo/.code={%
\pgfmathparse{##1 > 100 ? 100 + 10*(##1 - 100) : ##1}%
},%
%
% configure the allowed tick positions for the rain
% (UNTRANSFORMED!):
ytick={0,20,...,100,300,500,...,1000},
},
%
/wheather/temp min/.initial=,
/wheather/rain max/.initial=,
%
% USAGE: \pgfkeys{/wheather/set up={temp min=<min temperature>, rain max=<max rain axis value>}
% It will set up two styles "temp axis" and "rain axis". These
% styles will contain suitable axis limits and unit scales.
/wheather/set up/.code={%
\pgfkeysalso{/wheather/.cd,#1}%
%
% these values are supposed to be given:
\pgfkeysgetvalue{/wheather/rain max}\rainMax
\pgfkeysgetvalue{/wheather/temp min}\temperatureMin
%
% make sure they are given!
\ifx\rainMax\empty
\PackageError{wheather}{Please provide 'rain max=MAX RAIN VALUE IN AXIS'}{}%
\fi
\ifx\temperatureMin\empty
\PackageError{wheather}{Please provide 'temp min=MIN TEMPERATURE VALUE IN AXIS'}{}%
\fi
%
% now, compute the MISSING values. These are rain min and
% temperature max....
\begingroup
% do this in a group such that 'rain trafo' is only applied
% within the group...
%
% store it - just in case 'y coord trafo' is empty.
\let\pgfmathresult=\rainMax
%
\pgfplotsset{rain trafo,y coord trafo={\rainMax}}%
\global\let\rainMaxTransformed=\pgfmathresult
\pgfmathparse{\pgfmathresult /2}%
\global\let\temperatureMax=\pgfmathresult
\endgroup
%
\pgfmathparse{2*(\pgfkeysvalueof{/wheather/temp min})}%
\let\rainMin=\pgfmathresult
%
% now we want to compute a suitable axis scale for both axes.
% To this end, we scale them such that they fit into the value
% of \axisdefaultheight :
\pgfmathparse{\axisdefaultheight/(\temperatureMax-\temperatureMin)}%
\let\temperatureUnit=\pgfmathresult
%
\pgfmathparse{\axisdefaultheight/(\rainMaxTransformed-\rainMin)}%
\let\rainUnit=\pgfmathresult
%
% OK, compute the result:
\pgfplotsset{%
set layers,
%
% this is to be used for the temperature axis:
temp axis/.style={
y=\temperatureUnit,
ymin=\temperatureMin,
ymax=\temperatureMax,
%
% configure the allowed tick positions for a temperature:
ytick={-40,-30,-20,...,140},
% ... but only show the *label* for "small"
% temperatures:
yticklabel={%
\ifdim\tick pt<45pt
\pgfmathprintnumber\tick
\fi
},
ylabel={Temperature},
%tick pos=left,% seems to fail for 'axis x line=middle'!?
%
% configure the x axis:
axis x line*=middle,
xmin=1, xmax=12,
xtick={1,2,...,12},
xticklabels={J,F,M,A,M,J,J,A,S,O,N,D},
x tick label as interval,
grid=major,
},
%
% ... and this is to be used for the rain axis:
rain axis/.style={
y=\rainUnit,
ymin=\rainMin,
ymax=\rainMax,
% this range will be overwritten by 'rain trafo' if it
% is active:
ytick={0,20,...,400},
rain trafo,
yticklabel style={/pgf/number format/precision=0},
ylabel={Rain},
axis y line*=right,
hide x axis,
xmin=1, xmax=12,
},
}%
},
}
\begin{filecontents}{bombay.txt}
#bombay.txt
#M T/°C N/mm
1 23.9 3
2 23.9 3
3 26.1 3
4 28.1 2
5 29.7 18
6 28.9 485
7 27.2 617
8 27.0 340
9 27.0 264
10 28.1 64
11 27.2 13
12 25.6 3
\end{filecontents}
\begin{filecontents}{moskow.txt}
#M T/°C N/mm
1 -10.9 30
2 -12.9 23
3 -6.1 30
4 3.1 40
5 6.7 50
6 15.9 60
7 20.2 61
8 22.0 50
9 17.0 45
10 10.1 20
11 3.2 22
12 -9.6 25
\end{filecontents}
\begin{document}
\begin{tikzpicture}
\pgfplotsset{/wheather/set up={temp min=0, rain max=800}}
\def\filename{bombay.txt}
\begin{axis}[
temp axis,
]
\addplot+[red, mark=none] table [x index=0, y index=1] {\filename};
\end{axis}
\begin{axis}[
rain axis,
]
\addplot+[blue, mark=none] table [x index=0, y index=2] {\filename};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\pgfplotsset{
*clear* the nonlinear rain trafo. We do not want it here:
rain trafo/.style=,
/wheather/set up={temp min=-20, rain max=160},
}
\def\filename{moskow.txt}
\begin{axis}[
temp axis,
]
\addplot+[red, mark=none] table [x index=0, y index=1] {\filename};
\end{axis}
\begin{axis}[
rain axis,
]
\addplot+[blue, mark=none] table [x index=0, y index=2] {\filename};
\end{axis}
\end{tikzpicture}
\end{document}
我相信它已經相當不錯了,儘管它還剩下一些項目 - 主要是格式和填充路徑。
還有一個未解決的問題,實際上是 pgfplots 中的「缺失功能」:一旦有人寫入axis x line=middle
,pgfplots 就不會顯示第一個和最後一個刻度標籤。對於這個應用程式來說非常不幸。我會將其納入 pgfplots 的待辦事項清單中。也許你應該撤消axis x line=middle
來解決這個問題。請注意,將 x 個刻度顯示為間隔意味著您有 n-1 個刻度標籤用於 n 個刻度位置。簡而言之:您可能需要以某種方式複製一月份的資料點。