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

3
  • 1
    Could you please add the function in form of a typed text?
    – user121799
    Oct 28, 2018 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, 2018 at 16:21
  • oh sorry marmot just saw this comment now. Oct 28, 2018 at 18:16

1 Answer 1

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.

6
  • It would be much prettier if the sides were clearer than the upper faces.
    – AndréC
    Oct 28, 2018 at 16:46
  • 1
    @marmot I think OP meant lighter shade on the top surface as shown in question.
    – nidhin
    Oct 28, 2018 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, 2018 at 17:06
  • 1
    May be with \pgfdeclareplotmark ?
    – AndréC
    Oct 28, 2018 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. Oct 28, 2018 at 17:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .