如何將長條圖和折線圖與 pgfplots/tikz 結合?

如何將長條圖和折線圖與 pgfplots/tikz 結合?

我正在嘗試將條形圖和折線圖合併成一個圖形。我繪製了 3 種不同厚度的 5 種不同材料的品質。現在,我還有所有 15 個柱子的溫度數據。對於每種材料,我想將三個溫度數據點連接在一條線上,最好是傾斜的。如何將每個溫度值連接到對應的長條圖?

這是我到目前為止所得到的。 (對於材料 3 和 4,我只有一個溫度值,因此“僅標記”選項是可以的。)

長條圖和折線圖

\documentclass{article}
\usepackage{pgfplots}
\usepackage{anysize}
\pgfplotsset{compat=1.16}

\begin{document}   
\begin{figure}[!ht]
\centering
\pgfplotsset{width=14.5cm,
symbolic x coords={material1,material2,material3,material4,material5},
}
\begin{tikzpicture}
\begin{axis}
[
ybar=11pt,
axis x line*=bottom,
axis y line*=left,
ymin=0,ymax=1500,  
ylabel=material mass $\mathrm{[kg]}$, 
enlarge y limits=0.0,
enlarge x limits=0.15,
legend style={at={(1,-0.1)},draw=none}, 
legend columns=3,
x tick label style={text width=2.9cm,align=center},
xtick={data},
xtick align=inside,
minor y tick num=1,
height=0.37\linewidth,
bar width=0.5cm,
]
\addplot
[fill=black!30,draw=none] 
coordinates{
    (material1, 316.91)
    (material2,338.93)
    (material3,542.05)
    (material4,653.4)
    (material5,244.72)
};
\addplot
[fill=black!60,draw=none] 
coordinates{
    (material1,475.05)
    (material2,508.06)
    (material3,812.13 )
    (material4,979.44)
    (material5,366.83 )
};
\addplot
[fill=black!80,draw=none] 
coordinates{
    (material1,623.97)
    (material2,676.96)
    (material3,1084.65)
    (material4,1305.05)
    (material5,488.78)
};
\end{axis}
\begin{axis}
[
ymin=0,ymax=600,
axis y line*=right,
ylabel=temperature $\mathrm{[K]}$, 
enlarge y limits=0.0, 
enlarge x limits=0.15, 
height=0.37\linewidth,
xticklabels=\empty
]
\addplot[very thick,draw=red!90]
coordinates{
    (material1, 387.04)
    (material1,274.51)
    (material1,211.07)
};
\addplot[mark=circle,very thick,draw=red!90]
coordinates{
    (material2,461.93)
    (material2,326.88)
    (material2,253.97)
};
\addplot[only marks,very thick,draw=red!90]
coordinates{
    (material3,530.84)};
\addplot[only marks,very thick,draw=red!90]
coordinates{
    (material4,484.68)};
\addplot[mark=circle,very thick,draw=red!90]
coordinates{
    (material5,515.55)
    (material5,350.43)
    (material5,268.02)
};
\end{axis}
\end{tikzpicture}
\end{figure}
\end{document}

答案1

您會得到垂直線,因為當您不使用時,ybar座標不會改變。所以技巧是ybar在第二個axis環境中也使用。但因為您不想看到/顯示它們,所以我們使它們不可見,並透過濫用該nodes near coords功能來儲存座標。有了它們,就可以輕鬆地分別繪製線條和標記。

具體請看程式碼中的註解。
(請注意,我允許自己大幅簡化您的程式碼。我希望您同意這更具可讀性,因此更易於維護。)

% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{pgfplotstable}
    \pgfplotsset{
        compat=1.16,
        % create a custom style to store common `axis options`
        my axis style/.style={
            width=\linewidth,
            height=0.37\linewidth,
            ybar=5pt,       % <-- reduced so the bars don't overlap
            bar width=0.5cm,
            enlarge y limits=0.0,
            enlarge x limits=0.15,
            % to avoid to repeat the symbolic coords over and over again,
            % use them from a table ...
            xticklabels from table={\data}{material},
            % ... ensure that every data points get a corresponding xtick ...
            xtick={data},
            % ... and then just number the entries by the row index of the table
            table/x expr={\coordindex},
            xtick align=inside,
            minor y tick num=1,
        },
        % create a style to store the coordinates of the
        % temperature data
        Name/.style={
            % use the `nodes near coords` for that
            nodes near coords,
            nodes near coords style={
                % they shouldn't show any value ...
                coordinate,
                % but store coordinate labels which can later be used
                name=#1\coordindex,
            },
        },
    }
    % create a table of data
    % (which is much more clearly arranged than the "coordinates")
    % use any number that can clearly be distinguished from regular values to indicate
    % that you don't have any data here. In this case, I used -1.
    % (You can't use NaN here, because then no coordinate will be created and thus
    %  the (automatic) numbering of the named coordinates is working as expected.)
    \pgfplotstableread{
        material    d1      d2      d3      T1      T2      T3
        material1   316.91  475.05  623.97  387.04  274.51  211.07
        material2   338.93  508.06  676.96  461.93  326.88  253.97
        material3   542.05  812.13  1084.65 -1      530.84  -1
        material4   653.40  979.44  1305.05 -1      484.68  -1
        material5   244.72  366.83  488.78  515.55  350.43  268.02
    }{\data}
\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        % call the created style
        my axis style,
        % (list the remaining options)
        ymin=0,
        ymax=1500,
        axis x line*=bottom,
        axis y line*=left,
        ylabel=material mass $\mathrm{[kg]}$,
        % use a (custom) `cycle list` which is also much clearer than
        % providing the options to each `\addplot` command
        cycle list={
            {draw=none,fill=black!30},
            {draw=none,fill=black!60},
            {draw=none,fill=black!80},
        },
    ]
        % then this here is very simple
        % (and should be self-explanatory)
        \addplot table [y=d1] {\data};
        \addplot table [y=d2] {\data};
        \addplot table [y=d3] {\data};
    \end{axis}

    % here we also create a ybar plot, but don't draw the bars.
    % Instead, we just store named coordinates at the bar ends.
    \begin{axis}[
        my axis style,
        %
        ymin=0,
        ymax=600,
        axis y line*=right,
        ylabel=temperature $\mathrm{[K]}$,
        xticklabels=\empty,
        % make the bars invisible
        only marks,
    ]
        % use the custom `Name` style here to store the named coordinates
        \addplot [Name=a] table [y=T1] {\data};
        \addplot [Name=b] table [y=T2] {\data};
        \addplot [Name=c] table [y=T3] {\data};
    \end{axis}

    % the named coordinates can only be accessed after the `axis` environment.
    % Now simply draw the lines ...
    \foreach \i in {0,1,4} {
        \draw [very thick,red!90] (a\i) -- (b\i) -- (c\i);
    }

    % ... and marks
    \foreach \i in {2,3} {
        \fill [red!90] (b\i) circle [radius=2.5pt];
    }

\end{tikzpicture}
\end{document}

顯示上述程式碼結果的圖像

答案2

我必須重置您的設置的一些值才能獲得半合理的輸出並且沒有警告。訪問條的垂直位置的一種可能方法是使用nodes near coords自動命名這個答案。這允許人們重建繪圖。

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\begin{document}   
\begin{figure}[!ht]
\centering
\pgfplotsset{width=0.8\linewidth,
symbolic x coords={material1,material2,material3,material4,material5},
}
\pgfplotsset{% https://tex.stackexchange.com/a/75811/121799
    name nodes near coords/.style={nodes near coords={},
        every node near coord/.append style={anchor=center,coordinate,
            name=#1-\coordindex,%/utils/exec=\typeout{#1-\coordindex},
            alias=#1-last,
        },
    },
    name nodes near coords/.default=coordnode
}

\begin{tikzpicture}
\begin{axis}
[
ybar=11pt,
axis x line*=bottom,
axis y line*=left,
ymin=0,ymax=1500,  
ylabel=material mass $\mathrm{[kg]}$, 
enlarge y limits=0.0,
enlarge x limits=0.15,
legend style={at={(1,-0.1)},draw=none}, 
legend columns=3,
x tick label style={text width=2.9cm,align=center},
xtick={data},
xtick align=inside,
minor y tick num=1,
height=0.37\linewidth,
bar width=0.3cm,
]
\addplot
[fill=black!30,draw=none,name nodes near coords=m1] 
coordinates{
    (material1, 316.91)
    (material2,338.93)
    (material3,542.05)
    (material4,653.4)
    (material5,244.72)
};
\addplot
[fill=black!60,draw=none,name nodes near coords=m2] 
coordinates{
    (material1,475.05)
    (material2,508.06)
    (material3,812.13 )
    (material4,979.44)
    (material5,366.83 )
};
\addplot
[fill=black!80,draw=none,name nodes near coords=m3] 
coordinates{
    (material1,623.97)
    (material2,676.96)
    (material3,1084.65)
    (material4,1305.05)
    (material5,488.78)
};
\end{axis}
\begin{axis}
[
ymin=0,ymax=600,
axis y line*=right,
ylabel=temperature $\mathrm{[K]}$, 
enlarge y limits=0.0, 
enlarge x limits=0.15, 
height=0.37\linewidth,
xticklabels=\empty
]
\addplot[very thick,draw=red!90,opacity=0,name nodes near coords=n1]
coordinates{
    (material1, 387.04)
    (material1,274.51)
    (material1,211.07)
};
\addplot[mark=circle,very thick,draw=red!90,opacity=0,name nodes near coords=n2]
coordinates{
    (material2,461.93)
    (material2,326.88)
    (material2,253.97)
};
\addplot[only marks,very thick,draw=red!90]
coordinates{
    (material3,530.84)};
\addplot[only marks,very thick,draw=red!90]
coordinates{
    (material4,484.68)};
\addplot[mark=circle,very thick,draw=red!90,opacity=0,name nodes near coords=n5]
coordinates{
    (material5,515.55)
    (material5,350.43)
    (material5,268.02)
};
\end{axis}
\draw[very thick,draw=red!90] plot[samples at={0,1,2}] 
(m\the\numexpr\x+1\relax-0|-n1-\x);
\draw[mark=*,very thick,draw=red!90]
     plot[samples at={0,1,2}] (m\the\numexpr\x+1\relax-1|-n2-\x);
\draw[mark=*,very thick,draw=red!90]
     plot[samples at={0,1,2}] (m\the\numexpr\x+1\relax-4|-n5-\x);
\end{tikzpicture}
\end{figure}
\end{document}2

在此輸入影像描述

這是原則性的證明。我並沒有真正修復重疊的條形,因為我真的不知道你想要什麼輸出。但是,如果您在程式碼中修復了此問題,則可以使用此解決方案。我絕對不是說這是最優雅的解決方案。

相關內容