0

I must be missing something. There must be a way to have write_csv only export a column with 2 decimal points. For my use case, I could work with excel or csv or anything. But I need a file exported with two decimal points and it should be easy code.

var1<-sample(c("A","B"), size=10, replace=T)
var2<-rnorm(10, mean=5, sd=1)
var2
df<-data.frame(var1, var2)
library(readr)

#Try with xtable
library(xtable)
xtable(df, digits=2) %>% 
  write_csv(., file="test.csv")


1
  • 2
    There are soo many options. Like sprintf(), format, formatC, signif, round... see stackoverflow.com/q/3443687/28479453. My favourite would be var2<-signif(rnorm(10, mean=5, sd=1), digits = 2) Commented Feb 24 at 15:58

3 Answers 3

1

You can round the values to limit precision

df |> 
  dplyr::mutate(var2=round(var2, 2)) |>
  readr::write_csv(file="test.csv")

But that will still use default rules for printing decimal values. If you need an exact formatted string, you should use a function like format or sprintf to format your numbers exactly how you want.

Sign up to request clarification or add additional context in comments.

1 Comment

This seems the easiest although, wow, as much as I love R, I feel like this is something that could be done more simply!
1

Try formatC.

df |> transform(var2=formatC(var2, format='f', digits=2)) |> write.csv(file="test.csv")

Produces a .csv with this content:

"","var1","var2"
"1","A","4.89"
"2","A","6.51"
"3","A","4.91"
"4","A","7.02"
"5","B","4.94"
"6","B","6.30"
"7","B","7.29"
"8","B","3.61"
"9","A","4.72"
"10","B","4.87"

If you don't like the quotes and rownames, use write.csv(..., quote=FALSE, row.names=FALSE)

Note, that xtable::xtable(df) produces LaTeX code on the console and AFAIK has no file= argument.

Here alternatively a generalized data.table approach:

library(data.table)
dt[, (names(.SD)) := lapply(.SD, formatC, format = "f", digits = 2), 
   .SDcols = sapply(dt, is.numeric)]
fwrite(dt, file='test.csv')

produces:

var1,var2,date
A,4.89,2025-02-24
A,6.51,2025-02-24
A,4.91,2025-02-24
A,7.02,2025-02-24
B,4.94,2025-02-24
B,6.30,2025-02-24
B,7.29,2025-02-24
B,3.61,2025-02-24
A,4.72,2025-02-24
B,4.87,2025-02-24

Data:

> df |> dput()
structure(list(var1 = c("A", "A", "A", "A", "B", "B", "B", "B", 
"A", "B"), var2 = c(4.89387548390852, 6.51152199743894, 4.9053409615869, 
7.01842371387704, 4.93728590094758, 6.30486965422349, 7.28664539270111, 
3.61113929888766, 4.72121123318263, 4.86667866360634)), row.names = c(NA, 
-10L), class = "data.frame")
> dput(dt)
structure(list(var1 = c("A", "A", "A", "A", "B", "B", "B", "B", 
"A", "B"), var2 = c(4.89387548390852, 6.51152199743894, 4.9053409615869, 
7.01842371387704, 4.93728590094758, 6.30486965422349, 7.28664539270111, 
3.61113929888766, 4.72121123318263, 4.86667866360634), date = structure(c(20143, 
20143, 20143, 20143, 20143, 20143, 20143, 20143, 20143, 20143
), class = "Date")), row.names = c(NA, -10L), class = c("data.table", 
"data.frame"))

Comments

1

You could use custom formatting with readr through output_colum() generic, e.g. register your own output_column.double():

library(readr)
set.seed(42)

df <- 
  data.frame(
    var1 = sample(c("A", "B"), size = 5, replace = TRUE), 
    var2 = rnorm(5, mean = 5, sd = 1)
  )

# using readr::format_csv to check what readr::write_csv would store
format_csv(df) |> cat()
#> var1,var2
#> A,5.047884736094252
#> A,3.8954005593169416
#> A,5.539023801893912
#> A,5.580206320853481
#> B,4.342497164845326

# override output_column.double 
registerS3method("output_column", "double", \(x, name) sprintf("%.2f", x))
format_csv(df) |> cat()
#> var1,var2
#> A,5.05
#> A,3.90
#> A,5.54
#> A,5.58
#> B,4.34

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.