1

This question already has an answer here:

I am using y = {create col/linear regression={y=data}} with addplot to generate a line of best fit from data I'm pulling in from a file. How can I force the line to include the origin as a point it must pass through?

MWE:

\documentclass{article}

\usepackage{pgfplots}

\begin{document}
    \begin{figure}[H]
        \begin{tikzpicture}
            \begin{axis}
                \addplot table [
                    x = data1,
                    y = {create col/linear regression = {y = data2}}
                ] {data_file.txt};
            \end{axis}
        \end{tikzpicture}
    \end{figure}
\end{document}

marked as duplicate by Stefan Pinnow pgfplots Dec 21 '18 at 7:56

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 2
    I am sure that the chances of getting an answer will drastically increase when you add an MWE. It is also not clear what you are asking. The line is uniquely determined. How do you want to implement the additional constraint? Probably not by just shifting or rotating the line, right? – user121799 Dec 21 '18 at 1:08
  • @marmot Thanks for the tip, I've added the MWE. Regarding your question, I'm not sure: my thought was that there might be some built in mechanism by which some absolute data could be added. In my example, the point (0, 0) is known to be accurate, however the remaining points can be inaccurate which is what the best fit line is for. – VortixDev Dec 21 '18 at 1:20
  • 1
    Thanks for your update! (I am afraid without the data, it does not compile, but as far as I understand your question you could use something like this post.) Yet I am not sure what you are asking. I guess you need to specify how the line is determined. You could e.g. minimize the distances to the data points (with an appropriate definition of "distance"), but this might then be more a math question. – user121799 Dec 21 '18 at 1:27
1

I use an example of a random plot by Jake as a basis for a proposal of a possible way of drawing such a line. Whether this is "the" line you had in mind I cannot tell.

\documentclass[fleqn]{article}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.16}
% from https://tex.stackexchange.com/a/445369/121799
\newcommand*{\ReadOutElement}[4]{%
    \pgfplotstablegetelem{#2}{#3}\of{#1}%
    \let#4\pgfplotsretval
}
\begin{document}

\pgfmathsetseed{1138} % set the random seed
\pgfplotstableset{ % Define the equations for x and y
    create on use/x/.style={create col/expr={2*\pgfplotstablerow}},
    create on use/y/.style={create col/expr={2*(2*rand)^2+3*rand}}
}
% create a new table with 30 rows and columns x and y:
\pgfplotstablenew[columns={x,y}]{30}\loadedtable

\section*{``Theory''}

As I said in my comments, I do not know what you want to achieve. So I made an
assumption. Clearly, the only free parameter of a line running through the
origin is its slope, $a$. That is, the line is given by
\[ y(x)~=~a\,x\;.\] 
Call the data points $\{(x_i,y_i)_{1\le i\le n}\}$. One way to fix the line is
that the sum of all distances to the line vanishes, i.e.
\[ \sum\limits_{i=1}^n\left(a\,x_i-y_i\right)~=~0\;.\]
This implies that 
\[ a~=~\frac{\sum\limits_{i=1}^ny_i}{\sum\limits_{i=1}^nx_i}\;,\]
which is what is used below.

\section*{Example}

\pgfplotstablegetrowsof{\loadedtable}
\pgfmathtruncatemacro{\rownum}{\pgfplotsretval-1}
\pgfmathsetmacro{\sumx}{0}
\pgfmathsetmacro{\sumy}{0}
\pgfmathsetmacro{\xmax}{0}
\foreach \X in {0,...,\rownum}
{\ReadOutElement{\loadedtable}{\X}{x}{\tmpx}
\ReadOutElement{\loadedtable}{\X}{y}{\tmpy}
\pgfmathsetmacro{\sumx}{\sumx+\tmpx}
\xdef\sumx{\sumx}
\pgfmathsetmacro{\sumy}{\sumy+\tmpy}
\xdef\sumy{\sumy}
\pgfmathsetmacro{\xmax}{max(\xmax,\tmpx)}
\xdef\xmax{\xmax}}
\pgfmathsetmacro{\myslope}{\sumy/\sumx}



\begin{tikzpicture}
\begin{axis}[
xlabel=$x$, % label x axis
ylabel=$y$, % label y axis
axis lines=middle, %set the position of the axes
clip=false
]

\addplot [only marks] table {\loadedtable};
%\addplot [no markers, thick, red] table [y={create col/linear regression={y=y}}] {\loadedtable} node [anchor=west] {$\pgfmathprintnumber[precision=2, fixed zerofill]{\pgfplotstableregressiona} \cdot \mathrm{Weight} + \pgfmathprintnumber[precision=1]{\pgfplotstableregressionb}$};
\addplot [no markers, thick, red,domain=0:\xmax] {\myslope*x};
\end{axis}

\end{tikzpicture}
\end{document}

enter image description here

If you have another way of fixing the slope, a modification of this code may provide a way to achieve what you want.

  • Thats perfect: thank you so much! As a question of implementation, how might I set the data into \loadedtable from my file? I attempted to instead replace all instances of \loadedtable with my file name, but that produces "could not retrieve column 'x' from table" (and other errors) on the xmax definition – VortixDev Dec 21 '18 at 3:05
  • 1
    @VortixDev \pgfplotstableread{data.txt}\loadedtable (provided your file has the name data.txt) should work. And yes, if your data has other column names for the x and y coordinates, you need to adjust this as well. (I have to run but will be back in a few hours.) – user121799 Dec 21 '18 at 3:07
  • Works beautifully, thanks. You're right - I forgot to rename the field headers. – VortixDev Dec 21 '18 at 3:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.