8

I am trying to plot a 3d probability mass function like below (probability histogram for trinomial distribution). Could not find anything helpful online for 3D discrete plotting like below given a function (joint pmf). Kindly help.

enter image description here

Function:
enter image description here

The pic is from the book here Page 132. Probability and Statistical Inference By Hoggs et al.

Update:
Thanks to @marmot, I have managed to bring to a level as below. Yet to understand his code fully though.

enter image description here

  • 1
    Could you please add the function in form of a typed text? – user121799 Oct 28 '18 at 16:03
  • 1
    I think there are a lot of parameters. In order to plot you have to pick particular values, I think. – manooooh Oct 28 '18 at 16:21
  • oh sorry marmot just saw this comment now. – Parthiban Rajendran Oct 28 '18 at 18:16
11

Here is a proposal (1st EDIT: resolved dimension too large problems; 2nd EDIT: followed @AndréC's excellent suggestion to slightly redefine the cube plot mark. Redefining the cube mark actually allows one to get rid of one ugly point: unlike in my older answer, it is no longer necessary to cheat, i.e. to manually adjust the z ticks.). The colors of the faces of the 3D bars are set by the pgf keys cube top color and so on.

\documentclass[tikz,border=3.14pt]{standalone}
\usetikzlibrary{calc}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\pgfkeys{/tikz/.cd,
cube top color/.store in=\CubeTopColor,
cube top color=blue!60,
cube front color/.store in=\CubeFrontColor,
cube front color=blue!30,
cube side color/.store in=\CubeSideColor,
cube side color=blue!40,
}
\makeatletter
 \pgfdeclareplotmark{my cube*}
                {%
                        \pgfplots@cube@gethalf@x
                        \let\pgfplots@cube@halfx=\pgfmathresult
                        \pgfplots@cube@gethalf@y
                        \let\pgfplots@cube@halfy=\pgfmathresult
                        \pgfplots@cube@gethalf@z
                        \let\pgfplots@cube@halfz=\pgfmathresult
                        \pgfmathparse{0*\pgfplots@cube@halfz}
                        \let\pgfplots@cube@topz=\pgfmathresult
                        %
                        \pgfplotsifaxissurfaceisforeground{0vv}{%
                                \pgfsetfillcolor{\CubeFrontColor}
                                \pgfpathmoveto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathclose
                                \pgfusepathqfillstroke
                        }{% 
                                \pgfsetfillcolor{\CubeFrontColor}
                                \pgfpathmoveto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathclose
                                \pgfusepathqfillstroke
                        }%
                        \pgfplotsifaxissurfaceisforeground{v0v}{%
                                \pgfsetfillcolor{\CubeSideColor}
                                \pgfpathmoveto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathclose
                                \pgfusepathqfillstroke
                        }{% 
                                \pgfsetfillcolor{\CubeSideColor}
                                \pgfpathmoveto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathclose
                                \pgfusepathqfillstroke
                        }%
                        \pgfplotsifaxissurfaceisforeground{vv0}{%
                                \pgfsetfillcolor{\CubeTopColor}
                                \pgfpathmoveto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{-\pgfplots@cube@halfz}}%
                                \pgfpathclose
                                \pgfusepathqfillstroke
                        }{% 
                                \pgfsetfillcolor{\CubeTopColor}
                                \pgfpathmoveto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{-\pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{ \pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathlineto{\pgfplotsqpointxyz{ \pgfplots@cube@halfx}{-\pgfplots@cube@halfy}{\pgfplots@cube@topz}}%
                                \pgfpathclose
                                \pgfusepathqfillstroke
                        }%
            }
\makeatother

\begin{document}
\pgfmathsetmacro{\gconv}{2*326.32446}
% from https://tex.stackexchange.com/a/435234/121799
\begin{tikzpicture}[declare function={% (0.00001*\n!/(0.01*\x!*0.01*\y!*0.01*(\n-\x-\y)!))*
f(\x,\y,\px,\py,\n)=(0.000001*\n!/(0.01*\x!*0.01*\y!*0.01*(\n-\x-\y)!))*pow(\px,\x)*pow(\py,\y)*pow(1-\px-\py,\n-\x-\y);}] % 
\pgfplotsset{set layers}
\begin{axis}[% from section 4.6.4 of the pgfplotsmanual
        view={40}{40},
        %x dir=reverse,
        %y dir=reverse,
        width=320pt,
        height=280pt,
        mesh,
        %mesh/ordering=x varies,
        z buffer=auto,%reverse xy seq,
        xmin=-0.5,xmax=5.5,
        ymin=-0.5,ymax=5.5,
        zmin=0,zmax=0.3,
        enlargelimits=upper,
        ztick={0,0.15,0.3},
        xtick=data,
        extra tick style={grid=major},
        ytick={0,...,5},xtick={0,...,5},
        grid=minor,
        xlabel={$x$},
        ylabel={$y$},
        zlabel={$f(x,y)$},
        minor tick num=1,
        ]
\path let \p1=($(axis cs:0,0,1)-(axis cs:0,0,0)$) in 
\pgfextra{\pgfmathsetmacro{\conv}{2*\y1}
\ifx\gconv\conv
\typeout{z-scale\space good!}
\else
\typeout{Kindly\space consider\space setting\space the\space 
        prefactor\space of\space z\space to\space \conv}
\fi     
        };  
\path let \p1=($(axis cs:1,0,0)-(axis cs:0,0,0)$) in 
\pgfextra{\pgfmathsetmacro{\convx}{veclen(\x1,\y1)}
\typeout{One\space unit\space in\space x\space 
        direction\space is\space\convx pt}
        };                  
\path let \p1=($(axis cs:0,1,0)-(axis cs:0,0,0)$) in 
\pgfextra{\pgfmathsetmacro{\convy}{veclen(\x1,\y1)}
\typeout{One\space unit\space in\space y\space 
        direction\space is\space\convy pt}
        };
  \addplot3 [point meta=0,visualization depends on={
  \gconv*z \as \myz}, % you'll get told how to adjust the prefactor
  scatter/@pre marker code/.append style={/pgfplots/cube/size z=\myz},%
  scatter/@pre marker code/.append style={/pgfplots/cube/size x=24.3018pt},%
  scatter/@pre marker code/.append style={/pgfplots/cube/size y=21.71275pt},%
  scatter,only marks,
  mark=my cube*,mark size=5,opacity=1,domain=0:5,domain y=0:5,samples=6,samples y=6]
  {f(x,y,0.2,0.4,5)};
    \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

Notice that if you modify these plots, you may have to readjust \gconv as well as the x and y dimensions of the "cubes". However, the code will tell you which values you need to use.

  • It would be much prettier if the sides were clearer than the upper faces. – AndréC Oct 28 '18 at 16:46
  • 1
    @marmot I think OP meant lighter shade on the top surface as shown in question. – nidhin Oct 28 '18 at 16:48
  • @AndréC I do not think that this will be straightforward unless one as willing to draw the thing row by row. – user121799 Oct 28 '18 at 17:06
  • 1
    May be with \pgfdeclareplotmark ? – AndréC Oct 28 '18 at 17:23
  • thank you @marmot again my saviour for the day, and yeah, darker shade on top and ligher on sides of the bars could help in perceiving the plot a lot. I thought once we figure out plotting,customization could be easier. – Parthiban Rajendran Oct 28 '18 at 17:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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