5

I want to write a data frame into csv which contains numeric columns as well as character columns.

Some numeric columns are integers which I want to display as integers and some are decimals in which I need to control the number of digits after decimal and obviously no change in character columns

How can I do this? Eq a particular row in that dataframe is

XYZ  8200  0.306060606 ABC

Output should be

XYZ 8200 0.30 ABC

Regards

Jota
  • 17,281
  • 7
  • 63
  • 93
QuantLearner
  • 73
  • 1
  • 1
  • 8
  • 2
    Do you want to round the decimals? (e.g. `0.31` is closer to `0.306060606` than `0.30`) – Christopher Bottoms May 17 '15 at 04:48
  • Not required. But even if it happens its OK. My greater concern is truncation – QuantLearner May 17 '15 at 04:58
  • possible duplicate of [How to control number of decimal digits in write.table() output?](http://stackoverflow.com/questions/14260646/how-to-control-number-of-decimal-digits-in-write-table-output) – Jota May 17 '15 at 05:00
  • I saw that answer. I tried using format(), but I am not getting the required output – QuantLearner May 17 '15 at 05:05
  • See [how to make a great R reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). This works for me: `test <- data.frame("XYZ", 8200, 0.306060606, "ABC"); format(test, digits=2)` – Jota May 17 '15 at 05:09
  • Try this one and see what happens xyz <- data.frame(8200,365.2121,0.3060);format(xyz,digits=2) – QuantLearner May 17 '15 at 05:17
  • @Frank I am extremely sorry for my bad formatting. Will reiterate the comment. I tried the following thing and it did not work `xyz <- data.frame(8200,365.2121,0.3060);format(xyz,digits=2)` The reason is 365.2121 is converted to 365 – QuantLearner May 17 '15 at 05:36

1 Answers1

5

This will force two digits after the decimal place:

# read in some sample data
xyz <- data.frame(v1 = c("a", "b"), 
                  v2 = c(8200, 8100), 
                  v3 = c(365.2121, 365.2122), 
                  v4 = c(0.3060, 0.3260))

format(xyz, digits=2, nsmall=2)
#  v1      v2     v3   v4
#1  a 8200.00 365.21 0.31
#2  b 8100.00 365.21 0.33

If you don't want columns with whole numbers to also have those decimal places (e.g. column v2 in this example), you could do something like splitting xyz into columns that need to be formatted and other columns:

numbs2format <- 
    xyz[, (sapply(xyz, function(x) isTRUE(sum(x %% 1) > 0)))]
# ignore the warnings from trying to use %% on non-numerics
other.columns <- 
    xyz[, (sapply(xyz, function(x) !isTRUE(sum(x %% 1) > 0)))]

cbind(other.columns, format(numbs2format, digits=2, nsmall=2))
#  v1   v2     v3   v4
#1  a 8200 365.21 0.31
#2  b 8100 365.21 0.33
Jota
  • 17,281
  • 7
  • 63
  • 93
  • Hello, but then integer 8200 is displayed as 8200.00 which I dont want – QuantLearner May 18 '15 at 10:33
  • Hello, This is right but I could have used `as.integer()` as well to maintain the integer columns the way they are. I was searching for an answer within `write.csv()` whether it is directly available or not. That is, am I missing something. Data Modification was always an option open – QuantLearner May 20 '15 at 03:36
  • However I would still upvote this solution as to be more generic than `as.integer()` – QuantLearner May 20 '15 at 03:40
  • @QuantLearner So far as I know, there is no argument to `write.csv` that would allow you to achieve such a thing. So I answered with how to feed `write.csv` something in the appropriate format. If you have an approach you prefer using `as.integer`, feel free to post it as an answer, and even accept it if you want. – Jota May 20 '15 at 04:59