![TikZ:带残差的回归线](https://linux22.com/image/279883/TikZ%EF%BC%9A%E5%B8%A6%E6%AE%8B%E5%B7%AE%E7%9A%84%E5%9B%9E%E5%BD%92%E7%BA%BF.png)
期望输出
R
我使用制作了此图ggplot2
。现在我想使用 重现此图
Tikz
。我的 MWE 是:
\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\begin{document}
\pgfmathsetseed{1138} % set the random seed
\pgfplotstableset{ % Define the equations for x and y
create on use/x/.style={create col/expr={42+2*\pgfplotstablerow}},
create on use/y/.style={create col/expr={(0.6*\thisrow{x}+130)+5*rand}}
}
% create a new table with 30 rows and columns x and y:
\pgfplotstablenew[columns={x,y}]{30}\loadedtable
\begin{tikzpicture}
\begin{axis}[
xlabel=Weight (kg), % label x axis
ylabel=Height (cm), % label y axis
axis lines=left, %set the position of the axes
xmin=40, xmax=105, % set the min and max values of the x-axis
ymin=150, ymax=200, % set the min and max values of the y-axis
clip=false
]
\addplot [only marks] table {\loadedtable};
\addplot [no markers, thick, black] table [y={create col/linear regression={y=y}}] {\loadedtable} ;
\end{axis}
\end{tikzpicture}
\end{document}
任何帮助和提示都将不胜感激。谢谢
答案1
如果您明确创建一个regression
包含回归线值的新列(而不是使用样式create on demand
),则可以使用以下样式以不同的颜色绘制残差:
\pgfplotsset{
colored residuals/.style 2 args={
only marks,
scatter,
point meta=explicit,
colormap={redblue}{color=(#1) color=(#2)},
error bars/y dir=minus,
error bars/y explicit,
error bars/draw error bar/.code 2 args={
\pgfkeys{/pgf/fpu=true}
\pgfmathtruncatemacro\positiveresidual{\pgfplotspointmeta<0}
\pgfkeys{/pgf/fpu=false}
\ifnum\positiveresidual=0
\draw [#2] ##1 -- ##2;
\else
\draw [#1] ##1 -- ##2;
\fi
},
/pgfplots/table/.cd,
meta expr=(\thisrow{y}-\thisrow{regression})/abs(\thisrow{y}-\thisrow{regression}),
y error expr=\thisrow{y}-\thisrow{regression}
},
colored residuals/.default={red}{blue}
}
colored residuals={cyan}{orange}
您可以使用可选参数(例如)更改用于负残差和正残差的颜色。
\documentclass[tikz, border=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\begin{document}
\pgfmathsetseed{1138} % set the random seed
\pgfplotstableset{ % Define the equations for x and y
create on use/x/.style={create col/expr={42+2*\pgfplotstablerow}},
create on use/y/.style={create col/expr={(0.6*\thisrow{x}+130)+5*rand}}
}
% create a new table with 30 rows and columns x and y:
\pgfplotstablenew[columns={x,y}]{30}\loadedtable
% Calculate the regression line
\pgfplotstablecreatecol[linear regression]{regression}{\loadedtable}
\pgfplotsset{
colored residuals/.style 2 args={
only marks,
scatter,
point meta=explicit,
colormap={redblue}{color=(#1) color=(#2)},
error bars/y dir=minus,
error bars/y explicit,
error bars/draw error bar/.code 2 args={
\pgfkeys{/pgf/fpu=true}
\pgfmathtruncatemacro\positiveresidual{\pgfplotspointmeta<0}
\pgfkeys{/pgf/fpu=false}
\ifnum\positiveresidual=0
\draw [#2] ##1 -- ##2;
\else
\draw [#1] ##1 -- ##2;
\fi
},
/pgfplots/table/.cd,
meta expr=(\thisrow{y}-\thisrow{regression})/abs(\thisrow{y}-\thisrow{regression}),
y error expr=\thisrow{y}-\thisrow{regression}
},
colored residuals/.default={red}{blue}
}
\begin{tikzpicture}
\begin{axis}[
xlabel=Weight (kg), % label x axis
ylabel=Height (cm), % label y axis
axis lines=left, %set the position of the axes
xmin=40, xmax=105, % set the min and max values of the x-axis
ymin=150, ymax=200, % set the min and max values of the y-axis
]
\makeatletter
\addplot [colored residuals] table {\loadedtable};
\addplot [
no markers,
thick, black
] table [y=regression] {\loadedtable} ;
\end{axis}
\end{tikzpicture}
\end{document}
答案2
它有点冗长,但它做了它该做的事情。我在里面用一些注释来解释代码。
编辑 @Jake 方法更优雅,但我也得到了相同的结果,所以我在代码中添加了更改。
\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.9}
\begin{document}
\pgfmathsetseed{1138} % set the random seed
\pgfplotstableset{ % Define the equations for x and y
create on use/x/.style={create col/expr={42+2*\pgfplotstablerow}},
create on use/y/.style={create col/expr={(0.6*\thisrow{x}+130)+5*rand}}
}
% create a new table with 30 rows and columns x and y:
\pgfplotstablenew[columns={x,y}]{30}\loadedtable
% Determine no. of rows
\pgfplotstablegetrowsof{\loadedtable}
\pgfmathsetmacro{\rows}{\pgfplotsretval}
\pgfmathsetmacro{\r}{\rows-1}
\begin{tikzpicture}
\begin{axis}[
xlabel=Weight (kg), % label x axis
ylabel=Height (cm), % label y axis
axis lines=left, %set the position of the axes
xmin=40, xmax=105, % set the min and max values of the x-axis
ymin=150, ymax=200, % set the min and max values of the y-axis
clip=false]
\addplot [only marks] table {\loadedtable};
\addplot [no markers, thick, black] table [y={create col/linear regression={y=y}}] {\loadedtable};
% Save the coefficients of the linear regression
\pgfmathsetmacro{\rega}{\pgfplotstableregressiona}
\pgfmathsetmacro{\regb}{\pgfplotstableregressionb}
% loop on the number of rows
\foreach \i in {0,1,...,\r}{
% get element x and y of the table
\pgfplotstablegetelem{\i}{x}\of\loadedtable
\pgfmathsetmacro{\x}{\pgfplotsretval}
\pgfplotstablegetelem{\i}{y}\of\loadedtable
\pgfmathsetmacro{\y}{\pgfplotsretval}
\pgfmathsetmacro{\reg}{\rega*\x+\regb}
\pgfmathsetmacro{\dif}{\reg-\y}
% draw line between points and the linear regression
% the \edef\temp{\noexpand ... } is for using macro inside \foreach
\ifdim \dif px > 0px\relax
\edef\temp{\noexpand\draw[blue, thick] (axis cs:\x,\y)--(axis cs:\x,\reg);}
\edef\tempp{\noexpand\addplot[mark=*,blue] coordinates {(\x,\y)};}
\else
\edef\temp{\noexpand\draw[red, thick] (axis cs:\x,\y)--(axis cs:\x,\reg);}
\edef\tempp{\noexpand\addplot[mark=*,red] coordinates {(\x,\y)};}
\fi
\temp
\tempp
}
\end{axis}
\end{tikzpicture}
\end{document}