我正在尝试使用pgfplots
绘制数据的线性回归图。如果我的数据集的 X 分量中有一个nan
,则不会生成拟合,并显示警告:
NOTE: coordinate (nan,0.2) has been dropped because it is unbounded (in x). (see also unbounded coords=jump).
NOTE: coordinate (nan,nan) has been dropped because it is unbounded (in y). (see also unbounded coords=jump).
NOTE: coordinate (2,nan) has been dropped because it is unbounded (in y). (see also unbounded coords=jump).
NOTE: coordinate (3,nan) has been dropped because it is unbounded (in y). (see also unbounded coords=jump).
NOTE: coordinate (4,nan) has been dropped because it is unbounded (in y). (see also unbounded coords=jump).
以下 MWE 重现了该问题:
\documentclass[tikz, border=5mm]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.18}
% Successfully enables 'nan's in the Y component, but not X?
\makeatletter
% #1: keys
\def\pgfplotstable@linear@regression#1{%
\begingroup
\pgfqkeys{/pgfplots/table/create col/linear regression}{/pgf/fpu,#1}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/x}{\pgfplotstable@xsrc}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/y}{\pgfplotstable@ysrc}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/table}{\pgfplotstable@table}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/xmode}{\pgfplotstable@xmode}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/ymode}{\pgfplotstable@ymode}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/variance}{\pgfplotstable@variance@colname}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/variance list}{\pgfplotstable@variance@list}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/variance src}{\pgfplotstable@variance@table}%
%
\ifx\pgfplotstable@table\pgfutil@empty
\pgfutil@ifundefined{pgfplotstablename}{}{% query the name of the actual table struct
\let\pgfplotstable@table=\pgfplotstablename
}%
\fi
\ifx\pgfplotstable@table\pgfutil@empty
\pgfplots@error{Sorry, I couldn't determine a value for create col/linear regression/table. Which table should I load?}%
\fi
\ifx\pgfplotstable@xsrc\pgfutil@empty
\pgfplotsifinaddplottablestruct{%
\pgfutil@ifundefined{pgfplots@plot@tbl@x}{}{%
\let\pgfplotstable@xsrc=\pgfplots@plot@tbl@x
\ifx\pgfplotstable@ysrc\pgfutil@empty
\pgfplotstablegetcolsof\pgfplots@table
\ifnum\pgfplotsretval=2
\else
\pgfplotsthrow{invalid argument}{\pgfplotstable@ysrc}{Sorry, I don't which column should be used as `y' for the linear regression. Please provide 'linear regression={y=<colname>}'}\pgfeov%
\fi
\fi
}%
}{}%
\fi
\ifx\pgfplotstable@xsrc\pgfutil@empty
\def\pgfplotstable@xsrc{[index]0}%
\fi
\ifx\pgfplotstable@ysrc\pgfutil@empty
\def\pgfplotstable@ysrc{[index]1}%
\fi
%
\t@pgfplots@toka=\expandafter{\pgfplotstable@table}%
\t@pgfplots@tokb=\expandafter{\pgfplotstable@xsrc}%
\t@pgfplots@tokc=\expandafter{\pgfplotstable@ysrc}%
\edef\pgfplots@loc@TMPa{{\the\t@pgfplots@tokb}\noexpand\of{\the\t@pgfplots@toka}}%
\edef\pgfplots@loc@TMPb{{\the\t@pgfplots@tokc}\noexpand\of{\the\t@pgfplots@toka}}%
\expandafter\pgfplotstablegetcolumn\pgfplots@loc@TMPa\to\pgfplotstable@X
\expandafter\pgfplotstablegetcolumn\pgfplots@loc@TMPb\to\pgfplotstable@Y
%
\edef\pgfplotstable@xmode{\pgfplotstable@xmode}%
\expandafter\pgfplotstable@linear@regression@prepare@mode\expandafter{\pgfplotstable@xmode}{x}%%
\edef\pgfplotstable@ymode{\pgfplotstable@ymode}%
\expandafter\pgfplotstable@linear@regression@prepare@mode\expandafter{\pgfplotstable@ymode}{y}%%
%
\ifx\pgfplotstable@variance@list\pgfutil@empty
% check 'variance' key (loaded from table)
\pgfplotslistnewempty\pgfplotstable@VARIANCE
\ifx\pgfplotstable@variance@colname\pgfutil@empty
\else
\ifx\pgfplotstable@variance@table\pgfutil@empty
\t@pgfplots@toka=\expandafter{\pgfplotstable@table}%
\t@pgfplots@tokb=\expandafter{\pgfplotstable@variance@colname}%
\edef\pgfplots@loc@TMPa{{\the\t@pgfplots@tokb}\noexpand\of{\the\t@pgfplots@toka}}%
\expandafter\pgfplotstablegetcolumn\pgfplots@loc@TMPa\to\pgfplotstable@VARIANCE
\else
\t@pgfplots@toka=\expandafter{\pgfplotstable@variance@colname}%
\t@pgfplots@tokb=\expandafter{\pgfplotstable@variance@table}%
\edef\pgfplotstable@loc@TMPa{%
\noexpand\pgfplotstablegetcolumn{\the\t@pgfplots@toka}\noexpand\of{\the\t@pgfplots@tokb}\noexpand\to\noexpand\pgfplotstable@VARIANCE}%
\pgfplotstable@loc@TMPa
\fi
\fi
\else
% load from list:
\expandafter\pgfplotslistnew\expandafter\pgfplotstable@VARIANCE\expandafter{\pgfplotstable@variance@list}%
\fi
%
\pgfplotslistnewempty\pgfplotstable@Xparsed
%
\pgfmathfloatcreate{0}{0.0}{0}%
\let\pgfplotstable@S=\pgfmathresult
\let\pgfplotstable@Sxx=\pgfmathresult
\let\pgfplotstable@Sx=\pgfmathresult
\let\pgfplotstable@Sy=\pgfmathresult
\let\pgfplotstable@Sxy=\pgfmathresult
\pgfutil@loop
\pgfplotslistcheckempty\pgfplotstable@X
\ifpgfplotslistempty
\pgfplots@loop@CONTINUEfalse
\else
\pgfplots@loop@CONTINUEtrue
\fi
\ifpgfplots@loop@CONTINUE
\pgfplotslistpopfront\pgfplotstable@X\to\pgfplotstable@x
\pgfplotslistpopfront\pgfplotstable@Y\to\pgfplotstable@y
%
\pgfplotstableparsex{\pgfplotstable@x}%
\let\pgfplotstable@x=\pgfmathresult
\expandafter\pgfplotslistpushback\pgfmathresult\to\pgfplotstable@Xparsed
\pgfplotstableparsey{\pgfplotstable@y}%
\let\pgfplotstable@y=\pgfmathresult
\pgfmathfloatifflags{\pgfplotstable@y}{3}{}{% <---- This is new. The "3" stands for "nan"
%
\pgfplotslistcheckempty\pgfplotstable@VARIANCE
\ifpgfplotslistempty
\pgfmathfloatcreate{1}{1.0}{0}%
\let\pgfplotstable@invsqr=\pgfmathresult
\else
\pgfplotslistpopfront\pgfplotstable@VARIANCE\to\pgfplotstable@variance
\pgfmathfloatparsenumber{\pgfplotstable@variance}%
\let\pgfplotstable@variance=\pgfmathresult
\pgfmathfloatmultiply@{\pgfplotstable@variance}{\pgfplotstable@variance}%
\let\pgfplotstable@sqr=\pgfmathresult
\pgfmathfloatreciprocal@{\pgfplotstable@sqr}%
\let\pgfplotstable@invsqr=\pgfmathresult
\fi
%
\pgfmathfloatadd@{\pgfplotstable@S}{\pgfplotstable@invsqr}%
\let\pgfplotstable@S=\pgfmathresult
%
\pgfmathfloatmultiply@{\pgfplotstable@x}{\pgfplotstable@invsqr}%
\let\pgfplots@table@accum=\pgfmathresult
\pgfmathfloatadd@{\pgfplotstable@Sx}{\pgfplots@table@accum}%
\let\pgfplotstable@Sx=\pgfmathresult
%
\pgfmathfloatmultiply@{\pgfplotstable@x}{\pgfplots@table@accum}%
\let\pgfplots@table@accum=\pgfmathresult
\pgfmathfloatadd@{\pgfplotstable@Sxx}{\pgfplots@table@accum}%
\let\pgfplotstable@Sxx=\pgfmathresult
%
\pgfmathfloatmultiply@{\pgfplotstable@y}{\pgfplotstable@invsqr}%
\let\pgfplots@table@accum=\pgfmathresult
\pgfmathfloatadd@{\pgfplotstable@Sy}{\pgfplots@table@accum}%
\let\pgfplotstable@Sy=\pgfmathresult
%
\pgfmathfloatmultiply@{\pgfplotstable@x}{\pgfplots@table@accum}%
\let\pgfplots@table@accum=\pgfmathresult
\pgfmathfloatadd@{\pgfplotstable@Sxy}{\pgfplots@table@accum}%
\let\pgfplotstable@Sxy=\pgfmathresult
}% <---- This is new.
\pgfutil@repeat
%
\pgfmathparse{\pgfplotstable@S * \pgfplotstable@Sxx - \pgfplotstable@Sx *\pgfplotstable@Sx}%
\let\pgfplotstable@delta=\pgfmathresult
%
\pgfmathparse{(\pgfplotstable@S * \pgfplotstable@Sxy - \pgfplotstable@Sx * \pgfplotstable@Sy) / \pgfplotstable@delta}%
\let\pgfplotstable@a=\pgfmathresult
%
\pgfmathparse{(\pgfplotstable@Sxx * \pgfplotstable@Sy - \pgfplotstable@Sx * \pgfplotstable@Sxy) / \pgfplotstable@delta}%
\let\pgfplotstable@b=\pgfmathresult
%
\pgfplotslistnewempty\pgfplotstable@RESULT
\pgfplotslistforeachungrouped\pgfplotstable@Xparsed\as\pgfplotstable@x{%
\pgfmathfloatmultiply@{\pgfplotstable@x}{\pgfplotstable@a}%
\let\pgfplotstable@tmp=\pgfmathresult
\pgfmathfloatadd@{\pgfplotstable@tmp}{\pgfplotstable@b}%
\ifx\pgfplotstableparseylogbase\pgfutil@empty
\else
\pgfplotstableparseyinv@{\pgfmathresult}%
\fi
\pgfmathfloattosci{\pgfmathresult}%
\expandafter\pgfplotslistpushback\pgfmathresult\to\pgfplotstable@RESULT
}%
\pgfmathfloattosci\pgfplotstable@a
\let\pgfplotstable@a=\pgfmathresult
%
\pgfmathfloattosci\pgfplotstable@b
\let\pgfplotstable@b=\pgfmathresult
%
\global\let\pgfplotstableregressiona\pgfplotstable@a%
\global\let\pgfplotstableregressionb\pgfplotstable@b%
\let\pgfplotsretval=\pgfplotstable@RESULT
\pgfmath@smuggleone\pgfplotsretval
\endgroup
}%
\makeatother
% End nan-enabling macro
\begin{document}
\pgfplotstableread[col sep=comma]{
X, Y
nan, 0.2
2, 1
3, 2.5
4, 3
}\mytable
\begin{tikzpicture}
\begin{axis}
\addplot [only marks] table[] {\mytable};
\addplot [no markers] table[x=X,y={create col/linear regression={y=Y}}]{\mytable};
\end{axis}
\end{tikzpicture}
\end{document}
我怎样才能nan
同时拥有 X 和 Y 列并仍然生成拟合?
答案1
这将创建一个新列 Y2,当 X 为 nan 时,该列设置为 nan。
\documentclass[tikz, border=5mm]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.18}
% Successfully enables 'nan's in the Y component, but not X?
\makeatletter
% #1: keys
\def\pgfplotstable@linear@regression#1{%
\begingroup
\pgfqkeys{/pgfplots/table/create col/linear regression}{/pgf/fpu,#1}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/x}{\pgfplotstable@xsrc}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/y}{\pgfplotstable@ysrc}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/table}{\pgfplotstable@table}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/xmode}{\pgfplotstable@xmode}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/ymode}{\pgfplotstable@ymode}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/variance}{\pgfplotstable@variance@colname}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/variance list}{\pgfplotstable@variance@list}%
\pgfkeysgetvalue{/pgfplots/table/create col/linear regression/variance src}{\pgfplotstable@variance@table}%
%
\ifx\pgfplotstable@table\pgfutil@empty
\pgfutil@ifundefined{pgfplotstablename}{}{% query the name of the actual table struct
\let\pgfplotstable@table=\pgfplotstablename
}%
\fi
\ifx\pgfplotstable@table\pgfutil@empty
\pgfplots@error{Sorry, I couldn't determine a value for create col/linear regression/table. Which table should I load?}%
\fi
\ifx\pgfplotstable@xsrc\pgfutil@empty
\pgfplotsifinaddplottablestruct{%
\pgfutil@ifundefined{pgfplots@plot@tbl@x}{}{%
\let\pgfplotstable@xsrc=\pgfplots@plot@tbl@x
\ifx\pgfplotstable@ysrc\pgfutil@empty
\pgfplotstablegetcolsof\pgfplots@table
\ifnum\pgfplotsretval=2
\else
\pgfplotsthrow{invalid argument}{\pgfplotstable@ysrc}{Sorry, I don't which column should be used as `y' for the linear regression. Please provide 'linear regression={y=<colname>}'}\pgfeov%
\fi
\fi
}%
}{}%
\fi
\ifx\pgfplotstable@xsrc\pgfutil@empty
\def\pgfplotstable@xsrc{[index]0}%
\fi
\ifx\pgfplotstable@ysrc\pgfutil@empty
\def\pgfplotstable@ysrc{[index]1}%
\fi
%
\t@pgfplots@toka=\expandafter{\pgfplotstable@table}%
\t@pgfplots@tokb=\expandafter{\pgfplotstable@xsrc}%
\t@pgfplots@tokc=\expandafter{\pgfplotstable@ysrc}%
\edef\pgfplots@loc@TMPa{{\the\t@pgfplots@tokb}\noexpand\of{\the\t@pgfplots@toka}}%
\edef\pgfplots@loc@TMPb{{\the\t@pgfplots@tokc}\noexpand\of{\the\t@pgfplots@toka}}%
\expandafter\pgfplotstablegetcolumn\pgfplots@loc@TMPa\to\pgfplotstable@X
\expandafter\pgfplotstablegetcolumn\pgfplots@loc@TMPb\to\pgfplotstable@Y
%
\edef\pgfplotstable@xmode{\pgfplotstable@xmode}%
\expandafter\pgfplotstable@linear@regression@prepare@mode\expandafter{\pgfplotstable@xmode}{x}%%
\edef\pgfplotstable@ymode{\pgfplotstable@ymode}%
\expandafter\pgfplotstable@linear@regression@prepare@mode\expandafter{\pgfplotstable@ymode}{y}%%
%
\ifx\pgfplotstable@variance@list\pgfutil@empty
% check 'variance' key (loaded from table)
\pgfplotslistnewempty\pgfplotstable@VARIANCE
\ifx\pgfplotstable@variance@colname\pgfutil@empty
\else
\ifx\pgfplotstable@variance@table\pgfutil@empty
\t@pgfplots@toka=\expandafter{\pgfplotstable@table}%
\t@pgfplots@tokb=\expandafter{\pgfplotstable@variance@colname}%
\edef\pgfplots@loc@TMPa{{\the\t@pgfplots@tokb}\noexpand\of{\the\t@pgfplots@toka}}%
\expandafter\pgfplotstablegetcolumn\pgfplots@loc@TMPa\to\pgfplotstable@VARIANCE
\else
\t@pgfplots@toka=\expandafter{\pgfplotstable@variance@colname}%
\t@pgfplots@tokb=\expandafter{\pgfplotstable@variance@table}%
\edef\pgfplotstable@loc@TMPa{%
\noexpand\pgfplotstablegetcolumn{\the\t@pgfplots@toka}\noexpand\of{\the\t@pgfplots@tokb}\noexpand\to\noexpand\pgfplotstable@VARIANCE}%
\pgfplotstable@loc@TMPa
\fi
\fi
\else
% load from list:
\expandafter\pgfplotslistnew\expandafter\pgfplotstable@VARIANCE\expandafter{\pgfplotstable@variance@list}%
\fi
%
\pgfplotslistnewempty\pgfplotstable@Xparsed
%
\pgfmathfloatcreate{0}{0.0}{0}%
\let\pgfplotstable@S=\pgfmathresult
\let\pgfplotstable@Sxx=\pgfmathresult
\let\pgfplotstable@Sx=\pgfmathresult
\let\pgfplotstable@Sy=\pgfmathresult
\let\pgfplotstable@Sxy=\pgfmathresult
\pgfutil@loop
\pgfplotslistcheckempty\pgfplotstable@X
\ifpgfplotslistempty
\pgfplots@loop@CONTINUEfalse
\else
\pgfplots@loop@CONTINUEtrue
\fi
\ifpgfplots@loop@CONTINUE
\pgfplotslistpopfront\pgfplotstable@X\to\pgfplotstable@x
\pgfplotslistpopfront\pgfplotstable@Y\to\pgfplotstable@y
%
\pgfplotstableparsex{\pgfplotstable@x}%
\let\pgfplotstable@x=\pgfmathresult
\expandafter\pgfplotslistpushback\pgfmathresult\to\pgfplotstable@Xparsed
\pgfplotstableparsey{\pgfplotstable@y}%
\let\pgfplotstable@y=\pgfmathresult
\pgfmathfloatifflags{\pgfplotstable@y}{3}{}{% <---- This is new. The "3" stands for "nan"
%
\pgfplotslistcheckempty\pgfplotstable@VARIANCE
\ifpgfplotslistempty
\pgfmathfloatcreate{1}{1.0}{0}%
\let\pgfplotstable@invsqr=\pgfmathresult
\else
\pgfplotslistpopfront\pgfplotstable@VARIANCE\to\pgfplotstable@variance
\pgfmathfloatparsenumber{\pgfplotstable@variance}%
\let\pgfplotstable@variance=\pgfmathresult
\pgfmathfloatmultiply@{\pgfplotstable@variance}{\pgfplotstable@variance}%
\let\pgfplotstable@sqr=\pgfmathresult
\pgfmathfloatreciprocal@{\pgfplotstable@sqr}%
\let\pgfplotstable@invsqr=\pgfmathresult
\fi
%
\pgfmathfloatadd@{\pgfplotstable@S}{\pgfplotstable@invsqr}%
\let\pgfplotstable@S=\pgfmathresult
%
\pgfmathfloatmultiply@{\pgfplotstable@x}{\pgfplotstable@invsqr}%
\let\pgfplots@table@accum=\pgfmathresult
\pgfmathfloatadd@{\pgfplotstable@Sx}{\pgfplots@table@accum}%
\let\pgfplotstable@Sx=\pgfmathresult
%
\pgfmathfloatmultiply@{\pgfplotstable@x}{\pgfplots@table@accum}%
\let\pgfplots@table@accum=\pgfmathresult
\pgfmathfloatadd@{\pgfplotstable@Sxx}{\pgfplots@table@accum}%
\let\pgfplotstable@Sxx=\pgfmathresult
%
\pgfmathfloatmultiply@{\pgfplotstable@y}{\pgfplotstable@invsqr}%
\let\pgfplots@table@accum=\pgfmathresult
\pgfmathfloatadd@{\pgfplotstable@Sy}{\pgfplots@table@accum}%
\let\pgfplotstable@Sy=\pgfmathresult
%
\pgfmathfloatmultiply@{\pgfplotstable@x}{\pgfplots@table@accum}%
\let\pgfplots@table@accum=\pgfmathresult
\pgfmathfloatadd@{\pgfplotstable@Sxy}{\pgfplots@table@accum}%
\let\pgfplotstable@Sxy=\pgfmathresult
}% <---- This is new.
\pgfutil@repeat
%
\pgfmathparse{\pgfplotstable@S * \pgfplotstable@Sxx - \pgfplotstable@Sx *\pgfplotstable@Sx}%
\let\pgfplotstable@delta=\pgfmathresult
%
\pgfmathparse{(\pgfplotstable@S * \pgfplotstable@Sxy - \pgfplotstable@Sx * \pgfplotstable@Sy) / \pgfplotstable@delta}%
\let\pgfplotstable@a=\pgfmathresult
%
\pgfmathparse{(\pgfplotstable@Sxx * \pgfplotstable@Sy - \pgfplotstable@Sx * \pgfplotstable@Sxy) / \pgfplotstable@delta}%
\let\pgfplotstable@b=\pgfmathresult
%
\pgfplotslistnewempty\pgfplotstable@RESULT
\pgfplotslistforeachungrouped\pgfplotstable@Xparsed\as\pgfplotstable@x{%
\pgfmathfloatmultiply@{\pgfplotstable@x}{\pgfplotstable@a}%
\let\pgfplotstable@tmp=\pgfmathresult
\pgfmathfloatadd@{\pgfplotstable@tmp}{\pgfplotstable@b}%
\ifx\pgfplotstableparseylogbase\pgfutil@empty
\else
\pgfplotstableparseyinv@{\pgfmathresult}%
\fi
\pgfmathfloattosci{\pgfmathresult}%
\expandafter\pgfplotslistpushback\pgfmathresult\to\pgfplotstable@RESULT
}%
\pgfmathfloattosci\pgfplotstable@a
\let\pgfplotstable@a=\pgfmathresult
%
\pgfmathfloattosci\pgfplotstable@b
\let\pgfplotstable@b=\pgfmathresult
%
\global\let\pgfplotstableregressiona\pgfplotstable@a%
\global\let\pgfplotstableregressionb\pgfplotstable@b%
\let\pgfplotsretval=\pgfplotstable@RESULT
\pgfmath@smuggleone\pgfplotsretval
\endgroup
}%
\makeatother
% End nan-enabling macro
\begin{document}
\pgfplotstableread{
X Y
nan 0.25
2 1
3 2.5
4 3
}\mytable
\pgfplotstablecreatecol[create col/assign/.code={%
\pgfmathsetmacro{\X}{\thisrow{X}}%
\pgfmathsetmacro{\NAN}{nan}%
\ifx\NAN\X\relax
\let\newy=\NAN
\else
\edef\newy{\thisrow{Y}}%
\fi
\pgfkeyslet{/pgfplots/table/create col/next content}\newy
}]{Y2}\mytable
%\pgfplotstabletypeset{\mytable}
\begin{tikzpicture}
\begin{axis}
\addplot [only marks] table {\mytable};
\addplot [no markers] table[x=X,y={create col/linear regression={y=Y2}}]{\mytable};
\end{axis}
\end{tikzpicture}
\end{document}