总结如何制作原点位于右侧的水平条形图?
我想将多个图合并成一个独特的图形。我有一个自定义散点图,我想将其叠加在条形图之上,但我需要将条形图放在右侧,如下所示:
我想要那里的酒吧只是为了可视化,X-axis 仅适用于散点图。条形的值由外部计算。理想的解决方案是使用已填充const plot mark mid
、已旋转的 来填充右侧的空间并消除条形之间的间距。
我没有找到有关旋转的任何信息const plot mark mid
或更改条形图的整个参考系统的任何信息。我尝试采用这方法,添加x filter/.code={\pgfmathparse{-#1}\pgfmathresult}
到绘图中xbar
,但它也改变了散点图上的参考系统。任何帮助都将不胜感激。
地块详情:散点图是加权的,条形图表示是-值(它总结了一条水平走廊中该点的所有加权贡献)。
为了完整起见,这是代码的一个工作示例(但会产生左对齐的水平条):
\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot+[
scatter,
only marks,
point meta=explicit,
scatter/use mapped color={fill=gray, fill opacity=0.5, draw=black},
scatter/@pre marker code/.append style={/tikz/mark size=1+\pgfplotspointmetatransformed/100},
scatter/@post marker code/.code={
\ifdim\pgfplotspointmetatransformed pt> 200pt
\node[draw=black, fill=black, inner sep=0, shape=circle, minimum size=1] at (0pt,0pt) {};
\fi
\endscope
}
] table [x=x, y=y, meta=n] {
x y n
1.00 2.00 22.36
1.13 1.49 131.78
1.14 0.36 1189.32
1.22 0.99 449.04
1.33 0.50 1.96
1.33 1.32 48.04
1.33 2.00 3.92
1.34 1.66 60.80
1.39 0.94 330.23
1.42 1.31 145.24
};
\addplot+[xbar] table[x=score, y=key]{
key score
0.24 16.57
0.44 0.02
0.63 1.04
0.83 27.24
1.02 44.29
1.22 12.36
1.41 20.21
1.61 10.23
1.80 2.14
2.00 8.90
};
\end{axis}
\end{tikzpicture}
\end{document}
答案1
编辑:我找到了一个更干净的解决方案,axis
只需在同一个环境中使用两个不同的环境tikzpicture
。它甚至不需要改变直方图源。唯一要注意的细节是设置相同的 y 范围和调整xmin
xbar interval
将其缩小到右侧。该技巧用于x expr
使条形图中的所有值都变为负值,并从右到左显示它们。
\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
\pgfplotsset{width=12cm, height=8cm}
\begin{axis}[
xbar interval,
axis y line*=right, % Put everything on the right, in case you want markers
axis x line=none, % No x axis
grid=none, % No disturbing gridlines
ticks=none, % No ticks, it's just rough visualisation
ymin=0, ymax=2, % MANUALLY SET SAME RANGE
xmin=-2 % MANUALLY SHRINK THE GRAPH
]
% Inverx coordinate
\addplot+ table [x=score, y=key, x expr=-\thisrow{score}] {
score key
0.8174 2
0.8174 1.6
0.3967 1.2
0 0.8
0.4894 0.4
0.6977 0
};
\end{axis}
\begin{axis}[
axis y line*=left,
xmin=0, xmax=15,
ymin=0, ymax=2 % MANUALLY SET SAME Y-RANGE
]
\addplot+[
scatter,
only marks,
point meta=explicit,
scatter/use mapped color={fill=gray, fill opacity=0.5, draw=black},
% Changed the size of the marker to respect ``meta == c * area of the circle''
scatter/@pre marker code/.append style={/tikz/mark size=1+sqrt(\pgfplotspointmetatransformed/pi)/2},
scatter/@post marker code/.code={
\ifdim\pgfplotspointmetatransformed pt> 200pt
\node[draw=black, fill=black, inner sep=0, shape=circle, minimum size=1] at (0pt,0pt) {};
\fi
\endscope
}
] table [x=x, y=y, meta=n] {
x y n
1.424 0.7382 328.7
2.659 1.065 348.3
4.082 1.174 142
5.452 1.438 19.01
6 0.5 0.0005244
6.539 1.55 11
7.55 1.771 5
8.889 1.816 6
10.75 1.905 4
12.75 1.854 4
45.22 0.7315 2
47.13 0.4375 1
50.11 1.222 1
60.61 0.6087 1
86.86 1.143 1
};
\end{axis}
\end{tikzpicture}
\end{document}
编辑:旧的笨拙的解决方案。我设法用一种非常卑鄙的方式做到了这一点;我希望有人能想出比这更好的技巧。PGFPlots 在很多方面都很棒,但这似乎不是其中之一。因此,在 、 中的任何图中使用选项和会破坏x filter
图的布局。我不得不使用库并手动编辑坐标。直接使用它是不可能的,因为绘制了 x 的函数,而且我无法在不创建新的情况下旋转图。x expr
histogram
xbar
xbar interval
scatter
fillbetween
const plot
const plot
axis
在控制源数据后,我让程序输出直方图点的坐标,含义(在“伪python”中):
# assume that the distribution is normalized.
# histogram_intervals is the list of bins and size as tuple (min, max, score)
# and it's sorted by min ascending.
print(1.0, histogram_intervals[-1][1])
for rg_min, rg_max, score in reverse(histogram_intervals):
print(1.0 - score, interval_max)
print(1.0 - score, interval_min)
print(1.0, histogram_intervals[-1][0])
要点必须按顺序从上到下,因为fillbetween
否则图书馆将无法正确读取它们,并会在中间“扭曲”填充(见最后一张图)。
现在,将这些坐标绘制为散点图,将为您提供实际的直方图,其中条形从左到右,位于矩形中(0, min) rectangle (1, max)
。然后,我们的想法是将其向右移动xshift
(可能用缩放xscale
),然后填充该图与图右侧垂直线之间的区域。这假设您手动设置图形的 x 域。
完整工作示例:
\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{fillbetween}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
\pgfplotsset{width=12cm, height=8cm}
\begin{axis}[xmin=0, xmax=15]
\addplot+[
scatter,
only marks,
point meta=explicit,
scatter/use mapped color={fill=gray, fill opacity=0.5, draw=black},
% Changed the size of the marker to respect ``meta == c * area of the circle''
scatter/@pre marker code/.append style={/tikz/mark size=1+sqrt(\pgfplotspointmetatransformed/pi)/2},
scatter/@post marker code/.code={
\ifdim\pgfplotspointmetatransformed pt> 200pt
\node[draw=black, fill=black, inner sep=0, shape=circle, minimum size=1] at (0pt,0pt) {};
\fi
\endscope
}
] table [x=x, y=y, meta=n] {
x y n
1.424 0.7382 328.7
2.659 1.065 348.3
4.082 1.174 142
5.452 1.438 19.01
6 0.5 0.0005244
6.539 1.55 11
7.55 1.771 5
8.889 1.816 6
10.75 1.905 4
12.75 1.854 4
45.22 0.7315 2
47.13 0.4375 1
50.11 1.222 1
60.61 0.6087 1
86.86 1.143 1
};
% Add the histogram plot, with no drawing and no filling
\addplot+[
name path global=myhistogram,
xscale=2, % MANUAL TWEAK SCALE
xshift=40mm, % MANUAL TWEAK SHIFT
draw=none, no marks, fill=none
] table [x=x, y=y] {
x y
1 2
0.8174 2
0.8174 1.6
0.3967 1.6
0.3967 1.2
0 1.2
0 0.8
0.4894 0.8
0.4894 0.4
0.6977 0.4
0.6977 0
1 0
};
% Pick a vertical line at the right of the plot
% NOTE: MANUALLY PICK AXIS COORDINATES
\path[name path=myaxis] (axis cs: 14, 0) -- (axis cs:14, 2);
% Draw the region.
\addplot+ [draw=red, fill=red!50] fill between[of=myaxis and myhistogram];
\end{axis}
\end{tikzpicture}
\end{document}
如果你从下到上导出数据,将发生以下情况: