Estoy intentando combinar un gráfico de barras y un gráfico de líneas en una sola figura. Tracé la masa de 5 materiales diferentes para 3 espesores diferentes. Ahora también tengo datos de temperatura para las 15 barras. Para cada material, quiero conectar los tres puntos de datos de temperatura en una línea, preferiblemente inclinada. ¿Cómo conecto cada valor de temperatura a la barra respectiva?
Esto es lo que obtuve hasta ahora. (Para los materiales 3 y 4, solo tengo un valor de temperatura, por lo que la opción "solo marcas" está bien).
\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}
Respuesta1
Obtienes las líneas verticales, porque cuando no las usas ybar
no hay cambio de coordenadas. Entonces el truco consiste en usarlo también ybar
en el segundo axis
entorno. Pero como no desea verlos ni mostrarlos, los hacemos invisibles y simplemente almacenamos las coordenadas haciendo un mal uso de la nodes near coords
función. Al tenerlos es sencillo dibujar las líneas y marcas, respectivamente.
Para obtener más información, eche un vistazo a los comentarios en el código.
(Tenga en cuenta que me permití simplificar enormemente su código. Espero que esté de acuerdo en que es mucho más legible y, por lo tanto, más fácil de mantener).
% 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}
Respuesta2
Tuve que restablecer algunos valores de su configuración para obtener un resultado semi-razonable y sin advertencias. Una posible forma de acceder a las posiciones verticales de las barras es utilizar nodes near coords
el auto-nombramiento deesta respuesta. Esto permite reconstruir las tramas.
\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
Ésta es una prueba de principio. Realmente no arreglé las barras superpuestas porque realmente no tengo idea de qué resultado buscas. Sin embargo, si soluciona esto en su código, se puede utilizar esta solución. Definitivamente no estoy diciendo que esta sea la solución más elegante posible.