*! version 1.0  22 Sep 2003 N.Orsini & M.Bottai
*! version 2.0  04 Apr 2004 N.Orsini & M.Bottai (only changed help file)

program define grby
version 7


syntax varlist (min=2 max=3) [if] [in] [, MEans CI(string) COnnect NUmbers Format(string) SHading(integer 1) /*
					*/ YScale (numlist max=2) YLine(string) Vlabel V1label V2label /*
					*/ Title(string) SAving(string)]

preserve

		/* to use the option if/in */

			marksample touse, strok novarlist

		/* assign a progressive number to variables */

             	parse "`varlist'" , parse(" ")

			tempvar yvar xvar1

			qui gen  `yvar' = `1'
		 	qui gen  `xvar1' = `2'

		/* check option graph connect */

		if  "`connect'"  != "" {
				if  "`means'"  == "" {
							di in red "specify both the option means and ci(##)"
								exit 198
								}
						}

		/* check significance level for means */

		if  "`ci'"  != "" {
					if  "`means'"  == "" {
							di in red "specify the option means too"
								exit 198
								}

					if `ci' <10 | `ci' >99 {
								di in red "ci() invalid"
								exit 198
								}

					local level1  `ci'
					local level2 = `level1' * 0.005 + 0.50
					}

		/* check variable label */

			if "`vlabel'" != ""  {
				local lb: variable label `1'
				local lb1: variable label `2'
				}


			if "`3'" != ""  {
				tempvar xvar2
				qui gen  `xvar2' = `3'

					if "`vlabel'" != ""  {
						local lb2: variable label  `3'
						}
				}

		/*  extract value label xvar1 */

			if "`v1label'" != ""  {

			 	local vlb1: value label `2'
				tempvar last1
				sort `2'
				qui by `2':  gen byte `last1' = 1 if _n==_N  & `touse'

				local s 1
				local i 1

					while `s'<=_N {

						if `last1'[`s'] == 1 {

							local x =`2'[`s']

 							local labx1: label `vlb1' `x'
							local labx1`i' = abbrev(`"`labx1'"',7)

							local i = `i' + 1
							}

					local s= `s' + 1
	 				}
				}

			/*  extract value label xvar2 */

			if "`v2label'" != ""  {

				if "`3'" == ""  {
					di in red "specify the second variable"
					exit 198
					}

			 	local vlb2: value label `3'
				tempvar last2
				sort `3'
				qui by `3':  gen byte `last2' =1 if _n==_N  & `touse'

				local s 1
				local j 1

					while `s'<=_N {

						if `last2'[`s'] == 1 {

							local x=`3'[`s']

 						 		local labx2: label `vlb2' `x'
								local labx2`j' = abbrev(`"`labx2'"',12)


							local j = `j' + 1
							}

					local s= `s' + 1
	 				}
				}

		/* check the format */

           		if "`format'"=="" {
				 		if "`means'" != ""  {local fmt  "%3.2f"
								}
							else { local fmt  "%6.0g"
								}
						}
            	else {
				local fmt "`format'"
			}


		/* check the yline */

           		if "`yline'" != "" {
			             	local linea "`yline'"
						}

		/* check the shading */

			if `shading' < 0 | `shading' > 4 {

            		di in red "specify a shading from 0 to 4"
                        exit 198
				}


           		if "`shading'" == "" {
            		local sh = 2
				}
            		else {
				local sh = `shading'
			}


	/* some useful information about the variables */

		tempname arn amin amax crn cmin cmax

			qui tab `xvar1' if `touse', matrow(B)
			scalar arn = rowsof(B)
  			qui sum `xvar1' if `touse', mean
			scalar amin = r(min)
			scalar amax = r(max)

		if "`xvar2'" != ""  {
			qui tab `xvar2' if `touse', matrow(D)
			scalar crn = rowsof(D)
			qui sum `xvar2' if `touse', mean
			scalar cmin = r(min)
			scalar cmax = r(max)
			}
		else  {
			scalar crn = 1
			}


	tempname max min


	/* calculate sum or mean of depvar for each covariate pattern */

	local i 1
	local j 1
	local t 0

	tempname stop`i'`j' punto`i'`j' sum`i'`j'

	while `j'  <= crn  {

			if "`xvar2'" != ""  {
			local nvb`j' = D[`j',1]
			}

			while `i'  <= arn  {

					if "`xvar2'" != ""  {
				 		qui sum `yvar' if `xvar2'==D[`j',1] & `xvar1'==B[`i',1] & `touse'
						}
					else { qui sum `yvar' if `xvar1'==B[`i',1] & `touse'
						}

			  		if "`means'" != ""  {

								if r(N)== 0  {
								 	scalar stop`i'`j' = 1
									scalar punto`i'`j' = 0
									}

								if r(N)== 1 {

									if "`ci'" != "" {
										scalar sum`i'`j' = r(mean)
										scalar stop`i'`j' = 1
										scalar punto`i'`j' = 1
										local t = `t' + 1
											}
									else {
										scalar stop`i'`j' = 0
										scalar punto`i'`j' = 0
										scalar sum`i'`j' = r(mean)
										local t = `t' + 1
										}

									}

								if r(N)!= 0 & r(N) != 1 {

										scalar stop`i'`j' = 0
										scalar punto`i'`j' = 0
										scalar sum`i'`j' = r(mean)
										local t = `t' + 1
										}

								if "`ci'" != "" & stop`i'`j' != 1 {

									scalar ci`i'`j' = r(sd)*(invnorm(`level2')/sqrt(r(N)))
									scalar lowb`i'`j' = r(mean)- ci`i'`j'
									scalar uppb`i'`j' = r(mean)+ ci`i'`j'

											}
								}
					else {

							if r(N)== 0  {
									scalar punto`i'`j' = 0
								 	scalar stop`i'`j' = 1
									}

							if r(N)== 1  {
									scalar punto`i'`j' = 0
									scalar stop`i'`j' = 0
									scalar sum`i'`j' = r(sum)
									local t = `t' + 1
									}

								else  {
									scalar stop`i'`j' = 0
									scalar punto`i'`j' = 0
									scalar sum`i'`j' = r(sum)
									local t = `t' + 1
									}
							}

					if `j' == 1  {
							local nv`i' = B[`i',1]
							}


			if "`means'" == "" & "`ci'" == ""  {

				if stop`i'`j' == 0 & punto`i'`j' == 0  | stop`i'`j' == 0 & punto`i'`j' == 1 {

						if  `t'  == 1  {
								scalar max = sum`i'`j'
 								scalar min = sum`i'`j'
				  			       		}

                              	if sum`i'`j' > max {
                              	  	     scalar max = sum`i'`j'
                                     		        }


                              	if sum`i'`j' < min  {
                                    	scalar min = sum`i'`j'
										}
									}
						}


			if "`means'" != "" & "`ci'" == "" {

					if stop`i'`j' == 0 & punto`i'`j' == 0  | stop`i'`j' == 1 & punto`i'`j' == 1 {


						if `t' == 1  {
								scalar max = sum`i'`j'
 								scalar min = sum`i'`j'
				  			       		}

                              	if sum`i'`j' > max {
                              	  	     scalar max = sum`i'`j'
                                     		        }


                              	if sum`i'`j' < min  {
                                    	scalar min = sum`i'`j'
										}
					}
				}

			if "`means'" != "" & "`ci'" != "" & "`yscale'" == "" {

					if stop`i'`j' == 0 & punto`i'`j' == 0  {

						if `t' == 1  {
								scalar max = uppb`i'`j'
 								scalar min = lowb`i'`j'
				  			       		}

                              	if uppb`i'`j' > max {
                              	  	     scalar max = uppb`i'`j'
                                     		        }

                              	if lowb`i'`j' < min  {
                                    	scalar min = lowb`i'`j'
										}
								}


				     if stop`i'`j' == 1 & punto`i'`j' == 1 {

						if `t' == 1  {
								scalar max = sum`i'`j'
 								scalar min = sum`i'`j'
				  			       		}

						if sum`i'`j' > max {
                              	  	     scalar max = sum`i'`j'
                                     		        }

                              	if sum`i'`j' < min  {
                                    	scalar min = sum`i'`j'
										}
									}
						}

			if "`means'" != "" & "`ci'" != "" & "`yscale'" != "" {

					if stop`i'`j' == 0 & punto`i'`j' == 0 | stop`i'`j' == 1 & punto`i'`j' == 1 {

						if `t' == 1  {
								scalar max = sum`i'`j'
 								scalar min = sum`i'`j'
				  			       		}

                              	if sum`i'`j' > max {
                              	  	     scalar max = sum`i'`j'
                                     		        }

                              	if sum`i'`j' < min  {
                                    	scalar min = sum`i'`j'
										}

									}
				  			}



			local i = `i' + 1
           		}
      local i 1

	local j = `j' + 1

      }



	/* check the min and max value of the graph  */

 	tempvar min2 max2

			if "`yscale'" != ""  {

             			parse "`yscale'" , parse(" ")
					local min2 = `1'
					local max2 = `2'

					if `min2' > min    {
						di in red "specify a min value lowest than minimun value of yvar"
						exit 198
					}

					if `max2' < max    {
						di in red "specify a max value highest than maximum value of yvar"
						exit 198
					}

				}
			else {
				local max2 = max

				if "`ci'" == "" {
							local min2 = 0
							}
						else {
							local min2 = min
							}
				}
	/* control and cut upper and lower bound for means if option yscale is specified */

		local i 1
		local j 1

		if "`ci'" != "" & "`yscale'" != "" {

			while `j'  <= crn  {

					while `i'  <= arn  {

					if stop`i'`j' != 1  {

						if uppb`i'`j' > `max2' {
                              		       scalar uppb`i'`j' = `max2'
                                    		 	     }

						if lowb`i'`j' < `min2'  {
      	                              	scalar lowb`i'`j' = `min2'
							       		}
								}

 								local i = `i' + 1
								}
     		      			local i 1
		      			local j = `j' + 1
    						}
					}

	/* re-assign a progressive number to variables */

             	parse "`varlist'" , parse(" ")


	/* check saving  graph bar */

		if "`saving'" != ""  {
					gph open, saving(`saving')
					}
		else {
			gph open
			}

	/* graph bar the sum of depvar for each covariate pattern */

		gph pen 1

			if "`title'" != ""  {
				gph text 1000 16000 0 0 `title'
				}
		gph pen 2
			if "`vlabel'" != ""  {
				gph text 2300 16000 0 0  `lb'
				}
			else {
				gph text 2300 16000 0 0  `1'
				}

		gph pen 1
		gph line 4000 4000 19000 4000
		gph line 4000 3800 4000 4000

		local max3 = `max2'
		local max2 : display `fmt' `max2'
		gph text 4000 3500 0 1 `max2'
		local max2 = `max3'

		gph line 19000 4000 19000 32000
		gph line 19000 3800 19000 19000

		local min3 = `min2'
		local min2 : display `fmt' `min2'
		gph text 19000 3500 0 1 `min2'
		local min2 = `min3'

		gph pen 2

		if "`vlabel'" != ""  {
				gph text 20500 4000 0 1 `lb1'
				}
			else {
				gph text 20500 4000 0 1 `2'
				}

		if "`xvar2'" != ""  {

				if "`vlabel'" != ""  {
							gph text 22000 4000 0 1 `lb2'
							}
						else {
							gph text 22000 4000 0 1 `3'
							}
					}

	/* to share the available space */

		tempname  sv3 sv2 sv4 sv5 sv6 sv7 sv8 sv9 sv10 sv11

 		scalar sv3 = 28000 / crn
		scalar sv2 = sv3 / (arn + 2)

		scalar sv10  = (28000 - sv2)/crn
		scalar sv11 = sv10 / (arn + 1)

	  	scalar sv4 = (sv11 * arn)/2
 		scalar sv5 = sv11 / 2
 		scalar sv6 = 4000 + sv11
 		scalar sv7 = sv6 + sv5
 		scalar sv8 = (sv10 - sv11)/2
		scalar sv9 = 4000 + sv11 + sv8

	/* to convert data in coordinates  */

  		local ay = -(19000 - 4000)/ (`max2' - `min2')
		local by = 19000
     		local ax = 28000
		local bx = 4000

		local x1 = 4000
		local y2 = 19000
		local x2 = 4000 + sv11

		local i 0
      	local j 1
		local intex = sv7
		local intexb = sv9

	/* to screen yline */

		if "`yline'" != "" {

			if `linea' > `max2' | `linea' < `min2'  {
					di in r "specify another value for yline (between the lowest and the highest value)"
					exit 198
									}

			             	local yline1 = `linea'
			             	local yline2 = `yline1' -  `min2'
			             	local yline3 = `ay' * `yline2' + `by'
			             	gph pen 9
			             	gph line `yline3' 4000 `yline3' 32000
			             	gph pen 1
			             	gph text `yline3' 3500 0 1 `linea'
			             	gph line `yline3' 3800 `yline3' 4000
			             	gph pen 2
						}

	/* to screen graph bar  */

	while `j'  <= crn  {

              	while `i'  <= arn  {

				if `i' == 0   {
							local x1 = `x1' + sv11
						      local x2 = `x2' + sv11
					 	  }
				 else {
				 	 	if stop`i'`j' == 0 | punto`i'`j' == 1 {

							local y =  sum`i'`j'
							local y3 = `y' - `min2'
					 		local y1 = `ay' * `y3' + `by'

									 }

					if "`ci'" != ""  {

								if stop`i'`j' != 1  {

									local ub = uppb`i'`j'  - `min2'
			      			 		local ub2 = `ay' * `ub' + `by'
									local lb = lowb`i'`j' - `min2'
			      			 		local lb2 = `ay' * `lb' + `by'
							 	}

						if "`connect'" != ""  {

								if `i' > 1  {

									if stop`i'`j' == 1 & punto`i'`j' == 1 | stop`i'`j' == 0 & punto`i'`j' == 0 {

										local i = `i' - 1

									if stop`i'`j' == 1 & punto`i'`j' == 1 | stop`i'`j' == 0 & punto`i'`j' == 0 {

							 			local e =  sum`i'`j'
										local e3 = `e' - `min2'
					 					local e1 = `ay' * `e3' + `by'
									 						   }
										local i = `i' + 1
															}
										}
									    }
								}

					if "`ci'" == "" {

								if stop`i'`j' != 1  {
							    			   gph box `y1' `x1' `y2' `x2' `sh'
											}
								}
						else {
								if stop`i'`j' == 0   {

	  						       gph pen 3
							       gph line  `ub2' `intex' `lb2' `intex'
							 	 gph pen 2
								 gph point `y1' `intex' 225 4

												}

								if "`connect'" != "" {

									if `i' >= 2  {

									if stop`i'`j' == 1 & punto`i'`j' == 1 |  stop`i'`j' == 0 & punto`i'`j' == 0  {

										local i = `i' - 1

									if stop`i'`j' == 1 & punto`i'`j' == 1 |  stop`i'`j' == 0 & punto`i'`j' == 0 {

										 gph pen 9
							 			 gph line  `y1' `intex' `e1' `intexprec'

													 }
										local i = `i' + 1

													}
											 }
										}


						   	if stop`i'`j' == 1 & punto`i'`j' == 1 {
										 gph pen 2
										 gph point `y1' `intex' 275 7

													}

							}

					 gph pen 1
					 local y1 = `y1' - 120

					 local intex = `intex'

				if stop`i'`j' != 1 | punto`i'`j' == 1 {

				   	 local y : display `fmt' sum`i'`j'
				 	  	}


				if "`numbers'" != "" {

					if stop`i'`j' != 1 | punto`i'`j' == 1 {

							if "`ci'" != ""   {
							  	   	 gph text `y1' `intex' 0 1 `y'
													}
								else {
									 gph text `y1' `intex' 0 0 `y'
									}
									}
								}

					if "`v1label'" != ""  {
							gph text 20500 `intex' 0 0 `labx1`i''
							}
					else  {
						gph text 20500 `intex' 0 0 `nv`i''
						}

 					 gph pen 2
				  	 local x1 = `x1' + sv11
					 local x2 = `x2' + sv11
				       local intexprec = `intex'

					 local intex = `intex' + sv11

 		 			 }

			local i = `i' + 1
           		}

      local i 0
	gph pen 1

		if "`xvar2'" != ""  {

				if "`v2label'" != ""  {
							gph text 22000 `intexb' 0 0 `labx2`j''
							}
						else  {
							gph text 22000 `intexb' 0 0 `nvb`j''
							}
				}

	gph pen 2

	local j = `j' + 1

	 	local intex = `intex' + sv11

	 	local intexb = `intexb' + sv10
      }


      gph close

scalar drop _all

end