3

I am trying a 3d scatter plot as below, however marks are circles, appearing only in 2D always whichever view I choose. I want them to be flat on the X-Y plane. Please let me know how to do it. I tried "set layers" but that is pushing my entire graph down, behind next section's text. I think even the red line does the same, not giving me proper 3d perspective.

MWE:

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots, pgfplotstable}
\usetikzlibrary{math, decorations.pathreplacing,angles,quotes,bending, arrows.meta}
\pgfplotsset{compat=1.15}
\pgfplotstableread{
X Y Z m
2.2 14 0 0
2.7 23 0 0
3 13 0 0
3.55 22 0 0
4 15 0 0
4.5 20 0 0
4.75 28 0 0
5.5 23 0 0
}\datatable

\makeatletter
        \pgfdeclareplotmark{dot}
        {%
            \fill circle [x radius=0.02, y radius=0.08];
        }%
\makeatother

\begin{document}

\section{table using raw data in 3D}

The below diagram tries to replicate in 3D, the Figure 12.3 found in \cite{devore} , page 472 \\

% https://tex.stackexchange.com/questions/11251/trend-line-or-line-of-best-fit-in-pgfplots
\begin{tikzpicture}[scale=1.5]
\begin{axis}
    [   
    view={140}{50},
    xmin=1,xmax=6, ymin=5,ymax=40, zmin=0, zmax=10,
    % ytick=\empty,xtick=\empty,ztick=\empty,
    clip=false, axis lines = middle
    ]
    \addplot3[only marks, fill=cyan,mark=*] table {\datatable};
    \addplot3[thick, red] table[y={create col/linear regression={y=Y}}] {\datatable}; % compute a linear regression from the input table

    \def\X{2.7}
    \def\Y{23}
    \draw [-{Latex[length=4mm, width=2mm]}] (\X,\Y+10,12.5) node[right]{$(x_1,y_1)$} ..controls (0,5) .. (\X,\Y,0);
    \draw [-{Latex[length=4mm, width=2mm]}] (9,30,20) node[left, align=right]{\scriptsize True Regression Line\\ \scriptsize $y = \beta_0 + \beta_1 x$} .. controls (5,2.5) .. (5,22.7,0); 
    \draw [decorate, decoration={brace,amplitude=3pt}, xshift=0.5mm] (\X,\Y-0.1,0) to (\X,17,0) node[left, xshift=5mm, yshift=-1mm]{\scriptsize 1}; % brace 

    \draw [thick,dash pattern={on 7pt off 2pt on 1pt off 3pt}] (1,17.1) to (\X,17.1);
    \draw [thick,dash pattern={on 7pt off 2pt on 1pt off 3pt}] (\X,17.1) -- (\X,5);
    \node[above] at (\X,4) {$x_1$};
    \node[right, align=left,yshift=0.5mm] at (1,17.1) {$E(Y|x_1)=\mu_{Y.x_1}$};

\end{axis}
\end{tikzpicture}




  \begin{thebibliography}{1}
  \bibitem{devore} Jay. L Devore {\em Probability and Statistics for Engineering and the Sciences} 8th Edition.
  \end{thebibliography}


\end{document}

Output:
enter image description here

Stefan Pinnow
  • 29,535
  • If I look at your table, in every row the third entry is zero. Isn't that the z coordinate? What I want to say is that it is not too surprising that the circles are all in the x-y plane. So I think the points are correct, i.e. represent the data. Note that this is not a scatter plot in the strict sense since there is no scatter directive. Note also that you may drop \makeatletter and \makeatother. –  Oct 21 '18 at 17:15
  • If you could post the original figure from the book you cite, it will be easier to help. Most people here won't have access to it. – BambOo Oct 21 '18 at 17:29
  • @marmot I have added a new question here. can you please check out. Its continuation from this problem. – Parthiban Rajendran Oct 22 '18 at 08:38

1 Answers1

4

UPDATE: A version without hardcoded values. (Note that I use a not entirely harmless command: \globaldefs. The alternative will be longer. I believe that here using \globaldefs is OK.

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{pgfplots, pgfplotstable}
\usetikzlibrary{3d,calc,decorations.pathreplacing,arrows.meta}
% small fix for canvas is xy plane at z % https://tex.stackexchange.com/a/48776/121799
\makeatletter
\tikzoption{canvas is xy plane at z}[]{%
    \def\tikz@plane@origin{\pgfpointxyz{0}{0}{#1}}%
    \def\tikz@plane@x{\pgfpointxyz{1}{0}{#1}}%
    \def\tikz@plane@y{\pgfpointxyz{0}{1}{#1}}%
    \tikz@canvas@is@plane}
\makeatother
\pgfplotsset{compat=1.15}
\pgfplotstableread{
X Y Z m
2.2 14 0 0
2.7 23 0 0
3 13 0 0
3.55 22 0 0
4 15 0 0
4.5 20 0 0
4.75 28 0 0
5.5 23 0 0
}\datatable
\pgfplotstableread{
X Y Z m
2.2 0 0 0
2.7 0 0 0
3 13 0 0
3.55 0 0 0
4 15 0 0
4.5 0 0 0
4.75 0 0 0
5.5 0 0 0
}\datatabletwo


\pgfdeclareplotmark{fcirc}{%          
          \begin{scope}[expand style={local frame}{\MyLocalFrame},local frame]
          \begin{scope}[canvas is xy plane at z=0,transform shape]
            \fill circle(0.1);
          \end{scope}   
          \end{scope}
}%
% based on https://tex.stackexchange.com/a/64237/121799
\tikzset{expand style/.code n args={2}{\tikzset{#1/.style/.expanded={#2}}}}
\newcommand{\GetLocalFrame}{
    \path let \p1=($(1,0,0)-(0,0,0)$), \p2=($(0,1,0)-(0,0,0)$),
    \p3=($(0,0,1)-(0,0,0)$) in \pgfextra{
    \pgfmathsetmacro{\ratio}{veclen(\x1,\y1)/veclen(\x2,\y2)}
    \xdef\MyLocalFrame{   
                x   =  {   (\x1,\y1)    },
                y   =  {    (\ratio*\x2,\ratio*\y2)     },
                z   =   {     (\x3,\y3)     }
            }
    }; }

\begin{document}
\begin{tikzpicture}[scale=1.5]
\begin{axis}
    [   
    view={140}{50},
    xmin=1,xmax=6, ymin=5,ymax=40, zmin=0, zmax=10,
    % ytick=\empty,xtick=\empty,ztick=\empty,
    clip=false, axis lines = middle
    ]
    % read out the transformation done by pgfplots
    \GetLocalFrame
    \begin{scope}[transform shape]
    \addplot3[only marks, fill=cyan,mark=fcirc] 
    table {\datatable};
    \end{scope}
    \addplot3[thick, red] table[y={create col/linear regression={y=Y}}] {\datatable}; % compute a linear regression from the input table

    \def\X{2.7}
    \def\Y{23}
    \draw [-{Latex[length=4mm, width=2mm]}] (\X,\Y+10,12.5) node[right]{$(x_1,y_1)$} ..controls (0,5) .. (\X,\Y,0);
    \draw [-{Latex[length=4mm, width=2mm]}] (9,30,20) node[left, align=right]{\scriptsize True Regression Line\\ \scriptsize $y = \beta_0 + \beta_1 x$} .. controls (5,2.5) .. (5,22.7,0); 
    \draw [decorate, decoration={brace,amplitude=3pt}, xshift=0.5mm] (\X,\Y-0.1,0) to (\X,17,0) node[left, xshift=5mm, yshift=-1mm]{\scriptsize 1}; % brace 

    \draw [thick,dash pattern={on 7pt off 2pt on 1pt off 3pt}] (1,17.1) to (\X,17.1);
    \draw [thick,dash pattern={on 7pt off 2pt on 1pt off 3pt}] (\X,17.1) -- (\X,5);
    \node[above] at (\X,4) {$x_1$};
    \node[right, align=left,yshift=0.5mm] at (1,17.1) {$E(Y|x_1)=\mu_{Y.x_1}$};

\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

Old ANSWE: This is not an answer but just to show you what you get if do the projection.

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots, pgfplotstable}
\usetikzlibrary{3d,calc}
% small fix for canvas is xy plane at z % https://tex.stackexchange.com/a/48776/121799
\makeatletter
\tikzoption{canvas is xy plane at z}[]{%
    \def\tikz@plane@origin{\pgfpointxyz{0}{0}{#1}}%
    \def\tikz@plane@x{\pgfpointxyz{1}{0}{#1}}%
    \def\tikz@plane@y{\pgfpointxyz{0}{1}{#1}}%
    \tikz@canvas@is@plane}
\makeatother
\pgfplotsset{compat=1.15}
\pgfplotstableread{
X Y Z m
2.2 14 0 0
2.7 23 0 0
3 13 0 0
3.55 22 0 0
4 15 0 0
4.5 20 0 0
4.75 28 0 0
5.5 23 0 0
}\datatable
\pgfplotstableread{
X Y Z m
2.2 0 0 0
2.7 0 0 0
3 13 0 0
3.55 0 0 0
4 15 0 0
4.5 0 0 0
4.75 0 0 0
5.5 0 0 0
}\datatabletwo

%\makeatletter
        \pgfdeclareplotmark{dot}
        {%
            \fill circle [x radius=0.02, y radius=0.08];
        }%
%\makeatother

        \pgfdeclareplotmark{fcirc}
        {%
          \begin{scope}[x={(-21.20514pt,-9.26361pt)},
          y={(2.54181pt,-1.57715pt)},z={(0.0pt,6.04706pt)}]
          \begin{scope}[canvas is xy plane at z=0,transform shape]
            \fill circle(0.1);
          \end{scope}   
          \end{scope}
        }%


\begin{document}

\section{table using raw data in 3D}

The below diagram tries to replicate in 3D, the Figure 12.3 found in \cite{devore} , page 472 \\

% https://tex.stackexchange.com/questions/11251/trend-line-or-line-of-best-fit-in-pgfplots
\begin{tikzpicture}[scale=1.5]
\begin{axis}
    [   
    view={140}{50},
    xmin=1,xmax=6, ymin=5,ymax=40, zmin=0, zmax=10,
    % ytick=\empty,xtick=\empty,ztick=\empty,
    clip=false, axis lines = middle
    ]
    % read out the transformation done by pgfplots
    \path let \p1=($(1,0,0)-(0,0,0)$), \p2=($(0,1,0)-(0,0,0)$),
    \p3=($(0,0,1)-(0,0,0)$) in \pgfextra{\typeout{
    \x1,\y1;\x2,\y2;\x3,\y3}}; 
    \begin{scope}[transform shape]
    \addplot3[only marks, fill=cyan,mark=fcirc] 
    table {\datatable};
    \end{scope}
    \addplot3[thick, red] table[y={create col/linear regression={y=Y}}] {\datatable}; % compute a linear regression from the input table

    \def\X{2.7}
    \def\Y{23}
%     \draw [-{Latex[length=4mm, width=2mm]}] (\X,\Y+10,12.5) node[right]{$(x_1,y_1)$} ..controls (0,5) .. (\X,\Y,0);
%     \draw [-{Latex[length=4mm, width=2mm]}] (9,30,20) node[left, align=right]{\scriptsize True Regression Line\\ \scriptsize $y = \beta_0 + \beta_1 x$} .. controls (5,2.5) .. (5,22.7,0); 
%     \draw [decorate, decoration={brace,amplitude=3pt}, xshift=0.5mm] (\X,\Y-0.1,0) to (\X,17,0) node[left, xshift=5mm, yshift=-1mm]{\scriptsize 1}; % brace 
% 
%     \draw [thick,dash pattern={on 7pt off 2pt on 1pt off 3pt}] (1,17.1) to (\X,17.1);
%     \draw [thick,dash pattern={on 7pt off 2pt on 1pt off 3pt}] (\X,17.1) -- (\X,5);
%     \node[above] at (\X,4) {$x_1$};
%     \node[right, align=left,yshift=0.5mm] at (1,17.1) {$E(Y|x_1)=\mu_{Y.x_1}$};

\end{axis}
\end{tikzpicture}




  \begin{thebibliography}{1}
  \bibitem{devore} Jay. L Devore {\em Probability and Statistics for Engineering and the Sciences} 8th Edition.
  \end{thebibliography}


\end{document}

enter image description here

The circles are now properly projected on the x-y plane but, unfortunately, since the x and y scales look very different, they look like ellipse. Is that what you want?

On the other hand, if you want to cancel out the elliptic distortion, you can do that by cheating:

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots, pgfplotstable}
\usetikzlibrary{3d,calc,decorations.pathreplacing,arrows.meta}
% small fix for canvas is xy plane at z % https://tex.stackexchange.com/a/48776/121799
\makeatletter
\tikzoption{canvas is xy plane at z}[]{%
    \def\tikz@plane@origin{\pgfpointxyz{0}{0}{#1}}%
    \def\tikz@plane@x{\pgfpointxyz{1}{0}{#1}}%
    \def\tikz@plane@y{\pgfpointxyz{0}{1}{#1}}%
    \tikz@canvas@is@plane}
\makeatother
\pgfplotsset{compat=1.15}
\pgfplotstableread{
X Y Z m
2.2 14 0 0
2.7 23 0 0
3 13 0 0
3.55 22 0 0
4 15 0 0
4.5 20 0 0
4.75 28 0 0
5.5 23 0 0
}\datatable
\pgfplotstableread{
X Y Z m
2.2 0 0 0
2.7 0 0 0
3 13 0 0
3.55 0 0 0
4 15 0 0
4.5 0 0 0
4.75 0 0 0
5.5 0 0 0
}\datatabletwo

%\makeatletter
        \pgfdeclareplotmark{dot}
        {%
            \fill circle [x radius=0.02, y radius=0.08];
        }%
%\makeatother

        \pgfdeclareplotmark{fcirc}
        {%
          \begin{scope}[x={(-21.20514pt,-9.26361pt)},
          y={(7.73369*2.54181pt,-7.73369*1.57715pt)},z={(0.0pt,6.04706pt)}]
          \begin{scope}[canvas is xy plane at z=0,transform shape]
            \fill circle(0.1);
          \end{scope}   
          \end{scope}
        }%


\begin{document}

\section{table using raw data in 3D}

The below diagram tries to replicate in 3D, the Figure 12.3 found in \cite{devore} , page 472 \\

% https://tex.stackexchange.com/questions/11251/trend-line-or-line-of-best-fit-in-pgfplots
\begin{tikzpicture}[scale=1.5]
\begin{axis}
    [   
    view={140}{50},
    xmin=1,xmax=6, ymin=5,ymax=40, zmin=0, zmax=10,
    % ytick=\empty,xtick=\empty,ztick=\empty,
    clip=false, axis lines = middle
    ]
    % read out the transformation done by pgfplots
    \path let \p1=($(1,0,0)-(0,0,0)$), \p2=($(0,1,0)-(0,0,0)$),
    \p3=($(0,0,1)-(0,0,0)$) in \pgfextra{
    \pgfmathsetmacro{\ratio}{veclen(\x1,\y1)/veclen(\x2,\y2)}
    \typeout{
    \x1,\y1;\x2,\y2;\x3,\y3;\ratio}}; 
    \begin{scope}[transform shape]
    \addplot3[only marks, fill=cyan,mark=fcirc] 
    table {\datatable};
    \end{scope}
    \addplot3[thick, red] table[y={create col/linear regression={y=Y}}] {\datatable}; % compute a linear regression from the input table

    \def\X{2.7}
    \def\Y{23}
    \draw [-{Latex[length=4mm, width=2mm]}] (\X,\Y+10,12.5) node[right]{$(x_1,y_1)$} ..controls (0,5) .. (\X,\Y,0);
    \draw [-{Latex[length=4mm, width=2mm]}] (9,30,20) node[left, align=right]{\scriptsize True Regression Line\\ \scriptsize $y = \beta_0 + \beta_1 x$} .. controls (5,2.5) .. (5,22.7,0); 
    \draw [decorate, decoration={brace,amplitude=3pt}, xshift=0.5mm] (\X,\Y-0.1,0) to (\X,17,0) node[left, xshift=5mm, yshift=-1mm]{\scriptsize 1}; % brace 

    \draw [thick,dash pattern={on 7pt off 2pt on 1pt off 3pt}] (1,17.1) to (\X,17.1);
    \draw [thick,dash pattern={on 7pt off 2pt on 1pt off 3pt}] (\X,17.1) -- (\X,5);
    \node[above] at (\X,4) {$x_1$};
    \node[right, align=left,yshift=0.5mm] at (1,17.1) {$E(Y|x_1)=\mu_{Y.x_1}$};

\end{axis}
\end{tikzpicture}




  \begin{thebibliography}{1}
  \bibitem{devore} Jay. L Devore {\em Probability and Statistics for Engineering and the Sciences} 8th Edition.
  \end{thebibliography}


\end{document}

enter image description here

Unfortunately, because of the way pgfplots works, you need to run this, find out the transformation and the "cheating scale" \ratio, and then plug this in the definition of fcircle in case you make any changes.

  • why was the distortion earlier? because they scales are not equal for x and y? – Parthiban Rajendran Oct 21 '18 at 17:59
  • @BambOo It is just the ratio of lengths of unit vectors in x and y direction, which gets computed in \pgfmathsetmacro{\ratio}{veclen(\x1,\y1)/veclen(\x2,\y2)} in my code. –  Oct 21 '18 at 17:59
  • @PaariVendhan Precisely. Forget about 3D and just draw a circle in a plane in which the y scale is, say, 3 times the x scale. You'll get an ellipse, which is also what happens in my upper plot. By computing \pgfmathsetmacro{\ratio}{veclen(\x1,\y1)/veclen(\x2,\y2)} and installing it I make these scales equal in the local frame in which the circles are drawn. –  Oct 21 '18 at 18:00
  • But I wonder why this squeezing was not happening in 2D scale as my another example here – Parthiban Rajendran Oct 21 '18 at 18:03
  • Overleaf link goes to entire project. Please check file names (scatter plot 3D.tex) and (scatter plot 2D.tex) – Parthiban Rajendran Oct 21 '18 at 18:09
  • @PaariVendhan I regret to tell you that, because of some very bad previous experience, I do not follow overleaf links any more. Nonetheless you may try what happens if you add transform shape to your codes. –  Oct 21 '18 at 18:11
  • Here is the original image from the book – Parthiban Rajendran Oct 21 '18 at 18:14
  • I am not aware of transform shapes as newbie to tikz, I am learning but also unable to spend much time (this graph took whole day today to construct) :( – Parthiban Rajendran Oct 21 '18 at 18:15
  • What would be a better practice for me to get what I want, that markers be projected without squeeze just like they dont get squeezed on 2D plane? – Parthiban Rajendran Oct 21 '18 at 18:27
  • Because next I would want to place 2D normal distribution upon these markers like this – Parthiban Rajendran Oct 21 '18 at 18:29
  • @PaariVendhan I have done something of that sort here and also here. Does this allow you to do what you want? –  Oct 21 '18 at 20:31
  • sure thank you, will use it. and about other question, how could I have simplified or better practice for this issue? i want simplified code to build upon. the hard coded values dependent on data (fcirc) bother me. fcirc looks overkill for a simple 3D view of markers on 2D plane. – Parthiban Rajendran Oct 22 '18 at 03:31
  • @PaariVendhan I added a version that does not require you to add hardcoded coordinates. It is a bit hacky. –  Oct 22 '18 at 03:50
  • Can you please also explain what has been done? I tried to understand, but in vain. You are calling fcirc instead of dot or any other mark. fcirc draws a circle on a canvas on a local frame? If so I guess GetLocalFrame gives that? If I am correct this far, its still not clear what you are doing in GetLocalFrame – Parthiban Rajendran Oct 22 '18 at 05:31
  • Comments are not for extended discussion; this conversation has been moved to chat. – Joseph Wright Oct 22 '18 at 06:38
  • 1
    For the record: Jake's patch is now incorporated in v3.1 of TikZ. – Stefan Pinnow Jan 15 '19 at 19:25