I am trying to produce a markdown table using knitr::kable where the rounding of digits varies by rows. For example, suppose I have the following data.frame:
exa
If you have more than 4 or 5 rows, it may be worth using mapply()
to avoid having to repeat formatC(...)
once for each row.
example.df <- data.frame(a = c(0.1234, 2000), b = c(0.5678, 3000))
example.df1 <- data.frame(t(example.df)) # Transpose for easy iteration
example.df1 <- mapply( # Iterate over each column
function(df, digits) {
formatC(df, format="f", digits=digits)
},
df=example.df1, digits=c(2, 0)
)
example.df1 <- data.frame(t(example.df1)) # Transpose back
names(example.df1) <- names(example.df) # Re-create names
kable(example.df1, row.names=FALSE)
In the above code, you simply need to set df=
to the data.frame
or matrix
you want to turn into a table and digits=
to a vector indicating how many digits you want in each row.
Such a method could also be turned into a function if you were repeating it over multiple tables.
digitsByRows <- function(df, digits) {
tmp0 <- data.frame(t(df))
tmp1 <- mapply(
function(df0, digits0) {
formatC(df0, format="f", digits=digits0)
},
df0=tmp0, digits0=digits
)
tmp1 <- data.frame(t(tmp1))
names(tmp1) <- names(df)
return(tmp1)
}
kable(digitsByRows(example.df, c(2, 0)), row.names=FALSE)
As pointed out by @user20650, one solution consists in converting the format of the entries in your dataframe in R
before passing the data to knitr
. It could be done like this:
example.df <- rbind(formatC(as.numeric(example.df[1,]),format="f",digits=2),
formatC(as.numeric(example.df[2,]),format="d"))
colnames(example.df) <- c("a","b")
This gives the following output:
> kable(example.df, align="r")
| a| b|
|----:|----:|
| 0.12| 0.57|
| 2000| 3000|