Add asterisk p-value next to coefficients

Dear all,

I would like to ask for help. I would like to add an asterisk p-value (t-value) next to my coefficients for my output with 25 regressions at once.
I might use this, but I do not know how to apply it in this case.
mystars <- ifelse(p < .0001, "", ifelse(p < .001, " ", ifelse(p < .01, "** ", ifelse(p < .05, " ", " "))))
I appreciate any helps. My code and data are below.
Thank you in advance.

#Run three-factor model for 25 portfolios
fit.lm <- function(depvar) {
  mod <- lm(depvar ~ rmrf + SMB+ HML, data = reg)
  return(summary(mod))
}
output.lm <- lapply(reg[,paste0(rep("p", 25),1:25)], fit.lm)
coef.list <- list()
for (i in names(output.lm)) {
  coef.list[[i]] <- coef(output.lm[[i]])[,c("Estimate", "t value")]   #Estimate here include intercept and coefficients
  colnames(coef.list[[i]]) <- paste(i, colnames(coef.list[[i]]), sep = ".")
}
coef_reg<- do.call(cbind, coef.list)
coef_reg <- data.frame(coef_reg)
coef_reg<-coef_reg%>% mutate_if(is.numeric, ~round(., 3))
pick1<-select(coef_reg,p1.Estimate,p2.Estimate,p3.Estimate,p4.Estimate,p5.Estimate,p6.Estimate,p7.Estimate,p8.Estimate,p9.Estimate,p10.Estimate,p11.Estimate,p12.Estimate,p13.Estimate,p14.Estimate,p15.Estimate,p16.Estimate,p17.Estimate,p18.Estimate,p19.Estimate,p20.Estimate,p21.Estimate,p22.Estimate,p23.Estimate,p24.Estimate,p25.Estimate) 
pick2<-select(coef_reg,p1.t.value,p2.t.value,p3.t.value,p4.t.value,p5.t.value,p6.t.value,p7.t.value,p8.t.value,p9.t.value,p10.t.value,p11.t.value,p12.t.value,p13.t.value,p14.t.value,p15.t.value,p16.t.value,p17.t.value,p18.t.value,p19.t.value,p20.t.value,p21.t.value,p22.t.value,p23.t.value,p24.t.value,p25.t.value) 

#pick intercept, tvalue of 25 portfolios and arrange 

intercept<-filter(pick1,row_number()==1)
intercept<- matrix(intercept, ncol = 5, byrow = TRUE)
intercept <- data.frame(intercept)
t.value<-filter(pick2,row_number()==1)
t.value<- matrix(t.value, ncol = 5, byrow = TRUE)
t.value <- data.frame(t.value)
inter_3<-cbind(intercept,t.value)

reg<-data.frame(
      yearmm = c(200707,200708,200709,200710,200711,
                 200712,200801,200802,200803,200804),
        rmrf = c(-0.12, -0.01, 0.15, 0.01, -0.09, -0.05, -0.1, -0.22, -0.23, 0),
         SMB = c(0, -0.05, 0.13, 0.35, 0.02, 0.01, 0.01, -0.01, -0.03, 0),
         HML = c(-0.01, 0.07, 0.09, 0.26, 0.01, 0, -0.04, 0.01, -0.1, -0.07),
         RMW = c(-0.04, 0.05, -0.02, -0.02, 0.03, 0, -0.04, -0.01, -0.06, 0.01),
         CMA = c(0.02, -0.04, 0.01, 0.04, 0.01, 0.01, 0.01, -0.05, -0.03, -0.04),
         UMD = c(-0.04, 0.11, 0.05, 0.04, 0.05, -0.07, -0.06, 0.06, -0.08, -0.1),
          p1 = c(-0.1,-0.02,0.3,1.04,-0.16,-0.03,-0.07,
                 -0.38,-0.3,-0.07),
          p2 = c(-0.14,0.01,0.44,0.54,-0.1,-0.04,-0.13,
                 -0.16,-0.19,0.06),
          p3 = c(-0.14,0.02,0.26,0.48,-0.14,-0.02,
                 -0.13,-0.16,-0.22,-0.06),
          p4 = c(-0.07,-0.07,0.22,0.65,-0.07,-0.05,
                 -0.16,-0.23,-0.28,0.01),
          p5 = c(-0.06, -0.08, 0.45, 0.83, 0, -0.01, -0.15, -0.29, -0.38, 0.01),
          p6 = c(-0.14,-0.01,0.31,0.8,-0.08,-0.06,0.09,
                 -0.36,-0.34,-0.08),
          p7 = c(-0.03,0.04,0.16,0.27,-0.04,-0.05,
                 -0.09,-0.2,-0.28,-0.03),
          p8 = c(-0.08,0.02,0.18,0.36,-0.11,-0.04,
                 -0.09,-0.22,-0.22,-0.07),
          p9 = c(-0.12,0.01,0.28,0.58,-0.07,-0.08,
                 -0.16,-0.17,-0.4,-0.16),
         p10 = c(-0.09, -0.05, 0.32, 0.62, -0.08, -0.05, 0, -0.21, -0.37, -0.11),
         p11 = c(0.02, -0.07, 0.25, 0.4, 0, 0.04, -0.05, -0.18, -0.25, -0.11),
         p12 = c(-0.1, 0, 0.17, 0.17, -0.11, -0.05, -0.15, -0.16, -0.25, -0.04),
         p13 = c(-0.1,-0.05,0.18,0.47,-0.09,-0.08,
                 -0.05,-0.23,-0.2,-0.02),
         p14 = c(-0.11,0.09,0.13,0.22,-0.06,-0.05,
                 -0.12,-0.19,-0.3,-0.02),
         p15 = c(-0.04,-0.15,0.12,0.63,-0.13,-0.02,
                 -0.22,-0.27,-0.36,-0.11),
         p16 = c(-0.17,-0.04,0.24,0.26,-0.12,-0.05,
                 -0.12,-0.24,-0.25,-0.04),
         p17 = c(-0.07,-0.02,0.14,0.29,-0.11,-0.08,
                 -0.11,-0.18,-0.23,-0.09),
         p18 = c(-0.08,-0.01,0.14,0.06,-0.11,-0.03,
                 -0.08,-0.21,-0.23,0.04),
         p19 = c(-0.21,0.27,0.04,0.07,-0.06,-0.07,
                 -0.11,-0.24,-0.31,-0.11),
         p20 = c(-0.11, 0.02, 0.07, 0.15, -0.07, -0.05, -0.13, -0.25, -0.25, 0),
         p21 = c(-0.02,0.05,0.16,0.08,-0.08,-0.09,
                 -0.08,-0.19,-0.21,-0.11),
         p22 = c(0.04, 0, 0.14, 0.04, -0.11, -0.09, -0.07, -0.24, -0.17, 0.04),
         p23 = c(-0.07, 0, 0.08, 0.03, -0.07, -0.06, -0.08, -0.22, -0.21, 0.03),
         p24 = c(-0.11, 0.07, 0.1, 0.04, -0.1, -0.02, -0.1, -0.23, -0.28, -0.04),
         p25 = c(-0.03,-0.02,0.12,-0.01,-0.06,-0.05,
                 -0.12,-0.33,-0.32,-0.09)
)

You probably don't want what you think you want.

If you append * after a number it will cease to be numeric and you won't be able to do math with it anymore :crying_cat_face:
You are most likely more interested in simply formatting the display, which I can help you with. I'll show two ways to do it, the first is the simplest, we'll just create a function to format our data for us, we'll call this function print.pval. Normally I would advise against naming functions with periods (.), but we'll need it for the second where we create a whole new class of object which R will understand is a p-value.

First let's make some data which is likely to have some significant values.

x <- runif(100, 0, 0.2)

And now for the function,

print.pval <- function(x, digits = 6, ...) {
  # We can leverage the cut() function to do the heavy lifting for us here.
  # Setting the breakpoints where you indicated, when we pass in a numeric vector
  # We generate a factor with varying numbers of asterisks for labels.
  # Notably, only those values between 0 and 0.05 will be tagged.
  sig_level <- cut(x,
                   breaks = c(-Inf, 0, 0.0001, 0.001, 0.01, 0.05, Inf),
                   labels = c("", "****", "***", "**", "*", ""))
  # Next, we print the values, keeping only the set number of significant digits,
  # appending the asterisks, and making sure we don't include quotes so they
  # still look like numbers.
  print(paste0(signif(x, digits = digits), sig_level),
        quote = FALSE)
  # Finally, we return our x invisibly so printing doesn't modify the object.
  # That is x <- print.pval(x) doesn't change the object x.
  invisible(x)
}

And that's all there is to it,

head(x)
#> [1] 0.09635878 0.17378908 0.13695980 0.05801309 0.06256633 0.01963788
print.pval(head(x))
#> [1] 0.0963588  0.173789   0.13696    0.0580131  0.0625663  0.0196379*

Now, for something more fun... It would be great if R just knew the values were p-values and handled them accordingly. Well, it can!

We can create a very rudimentary "pval" class and R will do the rest.

We can start with a function which will coerce values to p-values.

as.pval <- function(x, ...) {
  structure(x, class = c("pval", class(x)))
}

We could, if we wanted, do something like,

as.pval <- function(x, ...) {
  structure(pmax(pmin(x, 1), 0), class = c("pval", class(x)))
}
sx <- as.pval(x)

Which has the effect of clamping the values to be between 0 and 1, but if you're actually computing p-values it shouldn't be required. Next, we can add some pval class methods to some simple functions, you can do as much or as little of this as you like.

`[[.pval` <- function(x, i, value) {
  as.pval(NextMethod())
}
`[.pval` <- function(x, i, value) {
  as.pval(NextMethod())
}
head.pval <- function(x, ...) {
  as.pval(NextMethod())
}

Finally, we can look at our handiwork,

head(x)
#> [1] 0.09635878 0.17378908 0.13695980 0.05801309 0.06256633 0.01963788
head(sx)
#> [1] 0.0963588  0.173789   0.13696    0.0580131  0.0625663  0.0196379*
(sx^2)[1:6]
#> [1] 0.00928501**   0.0302026*     0.018758*      0.00336552**   0.00391455**  
#> [6] 0.000385646***

Created on 2020-09-02 by the reprex package (v0.3.0)

I hope that helps, good luck!

1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.