Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Display p-values from lincom tests as marker labels in coefplot

    Dear statalist community,

    I am analyzing a dataset where I want to test different theories that might predict peoples attitudes towards income redistribution. The dataset contains information for six countries and can be divided into different sample subgroups (e.g. by political orientation of respondents). For further details see also my previous post: https://www.statalist.org/forums/for...ultiple-models.


    Here is an example dataset:

    Code:
    * Example generated by -dataex-. For more info, type help dataex
    clear
    input float(ideal_redis soc_mob left_wing right_wing) str5 country_survey
    12.100244  2.723296 1 0 "DEU"
     6.328649 3.8904226 0 0 "DEU"
    11.330771  1.556169 0 0 "DEU"
     7.114893  1.556169 0 0 "DEU"
    3.5471916   3.50138 0 1 "DEU"
      7.25711  1.556169 1 0 "DEU"
     6.222379 1.1671268 1 0 "GBR"
      1.63697  3.112338 0 1 "GBR"
     8.842057 2.3342535 0 1 "GBR"
     5.673986         0 0 0 "GBR"
     6.382203         0 0 0 "GBR"
    17.463827 1.1671268 0 1 "GBR"
    end
    label values soc_mob soc_mob
    label def soc_mob 0 "0 - There is not much opportunity", modify
    Recently I observed heterogeneity of effects from e.g. social mobility on attitudes towards income redistribution between sample subgroups (e.g. left-wing voters vs. right-wing voters) and across countries. Then I estimated whether differences between interactions of each left-wing and right-wing voters with social mobility are significant using lincom tests. The code I used is as follows:

    Code:
    foreach country in DEU GBR {
        
    reg ideal_redis c.soc_mob#(1.right_wing 1.left_wing) if country_survey=="`country'", robust
    
    eststo ideal_redis_`country'
    
    lincom 1.right_wing#c.soc_mob - 1.left_wing#c.soc_mob
        local ir_lc2_`country'_b=`r(estimate)'
        local ir_lc2_`country'_se=`r(se)'
        local ir_lc2_`country'_p=`r(p)'
    
    }
    I show interaction coefficients for each country in a graph using coefplot. Now I wondered, whether it's possible to display the p-values obtained from the lincom tests in the plot (maybe at the upper bound of the confidence intervals). From the help file I took that p-values from the regression can be displayed by using the mlabel(@pval) command, but I didn't figure out yet how to display p-values from separate lincom tests.
    Maybe one knows a way how to do that?

    Here is the code for the graph as well:

    Code:
    coefplot (ideal_redis_DEU, keep(1.right_wing#c.soc_mob) msymbol(s) msize(small) pstyle(p1) offset(0.15)) ///
    (ideal_redis_DEU, keep(1.left_wing#c.soc_mob) msymbol(t) msize(small) pstyle(p7) offset(-0.15)) ///
        ///
    (ideal_redis_GBR, keep(1.right_wing#c.soc_mob) msymbol(s) msize(small) pstyle(p1) offset(0.15)) ///
    (ideal_redis_GBR, keep(1.left_wing#c.soc_mob) msymbol(t) msize(small) pstyle(p7) offset(-0.15)) ///
       ///
    , aseq swapnames eqrename(ideal_redis_* = "" ) byopts(title("Marginal effects of political orientation by countries")) ///
    legend(order(2 "Right-wing" 4 "Left-Wing") size(vsmall) col(5) region(lwidth(vthin))) xline(0, lcolor(gs6) lpattern(dash)) ///
    xmlabel(-2.5(1)2.5, nogrid) xlabel(, grid glcolor(gs14)) ylabel(, grid glcolor(gs14)) ytick(, nogrid) graphregion(color(white)) ///
    subtitle(, size(medium)bcolor(white) lcolor(white)) plotregion(lcolor(black) margin(vsmall) lwidth(vthin)) bgcolor(white) xsize(5.5) ///
    mlabel(cond(@pval<.001, "****", cond(@pval<.01, "***", cond(@pval<.05, "**", cond(@pval<.1,"*", "")))))
    Thanks for your help, really appreciate it.
    Attached Files

  • #2
    The idea is to store the lincom estimates together with the regression estimates. However, I believe that lincom does not have a -post()- option, so use margins with the -expression()- option or nlcom and estadd (part of estout, from SSC) to add the results.

    See #4 in the linked thread for an illustration and post back if you are not able to implement the suggestion.

    https://www.statalist.org/forums/for...entage-changes
    Last edited by Andrew Musau; 18 Oct 2022, 09:57.

    Comment


    • #3
      Thanks for your response, Andrew. I tried to store the lincom estimates together with the regression estimates using lincom with the estadd command. Therefore, my code now looks as follows:

      Code:
      foreach country in DEU GBR {
          
      eststo ideal_redis_`country': quietly reg ideal_redis c.soc_mob#(1.right_wing 1.left_wing) c.immigr2#(1.right_wing 1.left_wing) if country_survey=="`country'", robust
      
      lincom 1.right_wing#c.soc_mob - 1.left_wing#c.soc_mob
      estadd scalar lincom_soc_mob_p = r(p)
      
      lincom 1.right_wing#c.immigr2 - 1.left_wing#c.immigr2
      estadd scalar lincom_immigr_p = r(p)
      
      esttab ideal_redis_`country', stats(lincom_soc_mob_p lincom_immigr_p)
      
      }
      However, I'm not sure whether my approach is correct since only the p-value of the first lincom test appears in the tables. I also tried following your suggestion using nlcom with the -post()- option, but didn't figure out yet how to store those estimates together with the regression estimates.

      How could I best proceed from here?





      Attached Files

      Comment


      • #4
        Are the p-values country-specific? If so and you just need the p-values, then just use locals and identify the statistics using the 3 letter country ISO codes.

        Code:
        * Example generated by -dataex-. For more info, type help dataex
        clear
        input float(ideal_redis soc_mob left_wing right_wing) str5 country_survey
        12.100244  2.723296 1 0 "DEU"
         6.328649 3.8904226 0 0 "DEU"
        11.330771  1.556169 0 0 "DEU"
         7.114893  1.556169 0 0 "DEU"
        3.5471916   3.50138 0 1 "DEU"
          7.25711  1.556169 1 0 "DEU"
         6.222379 1.1671268 1 0 "GBR"
          1.63697  3.112338 0 1 "GBR"
         8.842057 2.3342535 0 1 "GBR"
         5.673986         0 0 0 "GBR"
         6.382203         0 0 0 "GBR"
        17.463827 1.1671268 0 1 "GBR"
        end
        label values soc_mob soc_mob
        label def soc_mob 0 "0 - There is not much opportunity", modify
        
        foreach country in DEU GBR {
            
        reg ideal_redis c.soc_mob#(1.right_wing 1.left_wing) if country_survey=="`country'", robust
        lincom 1.right_wing#c.soc_mob - 1.left_wing#c.soc_mob
        local lab`country'= `:di %4.3f `r(p)''
        **# Bookmark #1
        eststo ideal_redis_`country'
        }
        
        coefplot (ideal_redis_DEU, keep(1.right_wing#c.soc_mob) msymbol(s) mlab("{it:p}=`labDEU'") mlabpos(12) msize(small) pstyle(p1) offset(0.15)) ///
        (ideal_redis_DEU, keep(1.left_wing#c.soc_mob) msymbol(t) msize(small) mlab("{it:p}=`labDEU'") mlabpos(12) pstyle(p7) offset(-0.15)) ///
            ///
        (ideal_redis_GBR, keep(1.right_wing#c.soc_mob) msymbol(s) msize(small) mlab("{it:p}=`labGBR'") mlabpos(12) pstyle(p1) offset(0.15)) ///
        (ideal_redis_GBR, keep(1.left_wing#c.soc_mob) msymbol(t) msize(small) mlab("{it:p}=`labGBR'") mlabpos(12) pstyle(p7) offset(-0.15)) ///
           ///
        , aseq swapnames eqrename(ideal_redis_* = "" ) byopts(title("Marginal effects of political orientation by countries")) ///
        legend(order(2 "Right-wing" 4 "Left-Wing") size(vsmall) col(5) region(lwidth(vthin))) xline(0, lcolor(gs6) lpattern(dash)) ///
        xmlabel(-2.5(1)2.5, nogrid) xlabel(, grid glcolor(gs14)) ylabel(, grid glcolor(gs14)) ytick(, nogrid) graphregion(color(white)) ///
        subtitle(, size(medium)bcolor(white) lcolor(white)) plotregion(lcolor(black) margin(vsmall) lwidth(vthin)) bgcolor(white) xsize(5.5) ///
        mlabel(cond(@pval<.001, "****", cond(@pval<.01, "***", cond(@pval<.05, "**", cond(@pval<.1,"*", "")))))
        Res.:

        Code:
         ( 1)  1.right_wing#c.soc_mob - 1.left_wing#c.soc_mob = 0
        
        ------------------------------------------------------------------------------
         ideal_redis | Coefficient  Std. err.      t    P>|t|     [95% conf. interval]
        -------------+----------------------------------------------------------------
                 (1) |  -2.299823     .75236    -3.06   0.055    -4.694168    .0945223
        ------------------------------------------------------------------------------
        
        
         ( 1)  1.right_wing#c.soc_mob - 1.left_wing#c.soc_mob = 0
        
        ------------------------------------------------------------------------------
         ideal_redis | Coefficient  Std. err.      t    P>|t|     [95% conf. interval]
        -------------+----------------------------------------------------------------
                 (1) |   1.639765   2.795934     0.59   0.599    -7.258145    10.53768
        ------------------------------------------------------------------------------
        Click image for larger version

Name:	Graph.png
Views:	1
Size:	44.7 KB
ID:	1686142

        Last edited by Andrew Musau; 20 Oct 2022, 14:21.

        Comment


        • #5
          Hi Andrew. I adopted your suggestion and I'm very happy with this solution!

          However, what I actually did now is to combine two subgraphs using the bylabel command, so that the left subgraph shows interactions of left-wing and right-wing with "social mobility" and the right subgraph interactions with "immigrant perception". My problem here is that both subgraphs display the same p-values obtained from the lincom tests. Maybe threre is a way to display the p-values correctly (different for both sides)?

          The example dataset is:

          Code:
          * Example generated by -dataex-. For more info, type help dataex
          clear
          input float(ideal_redis immigr2 soc_mob left_wing right_wing) str5 country_survey
           6.535077 2.5500395  1.556169 0 0 "DEU"
           7.080936 2.1857483  .7780845 0 1 "DEU"
          8.1762495 1.0928742 2.3342535 0 0 "DEU"
          12.100244  3.642914  2.723296 1 0 "DEU"
           6.328649  2.914331 3.8904226 0 0 "DEU"
          11.330771 1.4571655  1.556169 0 0 "DEU"
           7.114893  .7285827  1.556169 0 0 "DEU"
          3.5471916 3.2786224   3.50138 0 1 "DEU"
            7.25711 2.1857483  1.556169 1 0 "DEU"
           6.222379 2.1857483 1.1671268 1 0 "GBR"
            1.63697         0  3.112338 0 1 "GBR"
           8.842057         0 2.3342535 0 1 "GBR"
           5.673986  3.642914         0 0 0 "GBR"
           6.382203 1.4571655         0 0 0 "GBR"
          17.463827         0 1.1671268 0 1 "GBR"
             .35339         0  1.556169 0 0 "GBR"
           6.775779  .3642914  .3890423 1 0 "GBR"
          13.459105 1.0928742         0 0 0 "GBR"
          .09163618 3.2786224  3.112338 0 1 "GBR"
          end
          label values immigr2 immigr2
          label def immigr2 0 "0 - Our culture is undermined by immigrants", modify
          label values soc_mob soc_mob
          label def soc_mob 0 "0 - There is not much opportunity", modify
          The code for the regression would be:

          Code:
          foreach country in DEU GBR {
              
          reg ideal_redis c.soc_mob#(1.right_wing 1.left_wing) c.immigr2#(1.right_wing 1.left_wing) if country_survey=="`country'", robust
          
          lincom 1.right_wing#c.soc_mob - 1.left_wing#c.soc_mob
          local lab`country'= `:di %4.3f `r(p)''
          
          lincom 1.right_wing#c.immigr2 - 1.left_wing#c.immigr2
          local lab2`country'= `:di %4.3f `r(p)''
          
          eststo ideal_redis_`country'
          }
          And the code for the graph now is:

          Code:
          coefplot (ideal_redis_DEU, keep(1.right_wing#c.soc_mob) mlab(cond(@pval<.001, "****", cond(@pval<.01, "***", cond(@pval<.05, "**", cond(@pval<.1,"*", ""))))) ///
          msymbol(s) mlabpos(12) msize(small) pstyle(p1) offset(0.2)) ///
          (ideal_redis_DEU, keep(1.left_wing#c.soc_mob) mlab(cond(@pval<.001, "****", cond(@pval<.01, "***", cond(@pval<.05, "**", cond(@pval<.1,"*", "")))) + ("   {it:p}=`labDEU'")) ///
          mlabpos(12) mlabpos(12) msymbol(t) msize(small) pstyle(p7) offset(-0.2)) ///
              ///
          (ideal_redis_GBR, keep(1.right_wing#c.soc_mob) mlab(cond(@pval<.001, "****", cond(@pval<.01, "***", cond(@pval<.05, "**", cond(@pval<.1,"*", ""))))) ///
          msymbol(s) mlabpos(12) msize(small) pstyle(p1) offset(0.2)) ///
          (ideal_redis_GBR, keep(1.left_wing#c.soc_mob) mlab(cond(@pval<.001, "****", cond(@pval<.01, "***", cond(@pval<.05, "**", cond(@pval<.1,"*", "")))) + ("   {it:p}=`labGBR'")) ///
          msymbol(t) mlabpos(12) msize(small) pstyle(p7) offset(-0.2)), bylabel(Interaction with social mobility) || /// ///
             ///
          (ideal_redis_DEU, keep(1.right_wing#c.immigr2) mlab(cond(@pval<.001, "****", cond(@pval<.01, "***", cond(@pval<.05, "**", cond(@pval<.1,"*", ""))))) ///
          msymbol(s) mlabpos(12) msize(small) pstyle(p1) offset(0.2)) ///
          (ideal_redis_DEU, keep(1.left_wing#c.immigr2) mlab(cond(@pval<.001, "****", cond(@pval<.01, "***", cond(@pval<.05, "**", cond(@pval<.1,"*", "")))) + ("   {it:p}=`lab2DEU'")) ///
          msymbol(t) mlabpos(12) msize(small) pstyle(p7) offset(-0.2)) ///
              ///
          (ideal_redis_GBR, keep(1.right_wing#c.immigr2) mlab(cond(@pval<.001, "****", cond(@pval<.01, "***", cond(@pval<.05, "**", cond(@pval<.1,"*", ""))))) ///
          msymbol(s) mlabpos(12) msize(small) pstyle(p1) offset(0.2)) ///
          (ideal_redis_GBR, keep(1.left_wing#c.immigr2) mlab(cond(@pval<.001, "****", cond(@pval<.01, "***", cond(@pval<.05, "**", cond(@pval<.1,"*", "")))) + ("   {it:p}=`lab2GBR'")) ///
          msymbol(t) mlabpos(12) msize(small) pstyle(p7) offset(-0.2)), bylabel(Interaction with immigrant perception) || ///     ///
             ///
          , aseq swapnames eqrename(ideal_redis_* = "") byopts(title("Marginal effects of political orientation by countries")) ///
          legend(order(2 "Right-wing" 4 "Left-Wing") size(vsmall) col(5) region(lwidth(vthin))) xline(0, lcolor(gs6) lpattern(dash)) ///
          xmlabel(-2.5(1)2.5, nogrid) xlabel(, grid glcolor(gs14)) ylabel(, grid glcolor(gs14)) ytick(, nogrid) graphregion(color(white)) ///
          subtitle(, size(medium)bcolor(white) lcolor(white)) plotregion(lcolor(black) margin(vsmall) lwidth(vthin)) bgcolor(white) xsize(5.5)
          I think it is probably getting a bit complicated here. If there is no straight forward solution for this, I could as well change the values on one side with the graph editor afterwards. In any way thanks a lot for your help.

          Comment


          • #6
            *Here's the graph as well.

            Click image for larger version

Name:	Graph.png
Views:	2
Size:	76.9 KB
ID:	1686201
            Attached Files

            Comment


            • #7
              I do not have time to look at this until the end of the week when my schedule clears up, but some previous posts with the same theme include:

              1. Using the -addplot()- option and plotting the p-values as marker labels of an added invisible scatter plot: https://www.statalist.org/forums/for...-each-by-graph

              2. Plotting each subgraph separately and using gr combine: https://www.statalist.org/forums/for...nsplot-example
              Last edited by Andrew Musau; 24 Oct 2022, 02:18.

              Comment

              Working...
              X