2

I should write a txt file with a specific format based on fixed-width columns (e.g. 1st variable in the columns 1-8, 2nd variable in the columns 9-15...).

The original data have different length and they have to be put on the right of the assigned columns. For example: the values "-15.96" and "12.489" have to be written in the columns 1-8 of the first and the second line, while "-872.6" and "1723.6" in the columns 9-15. This will be:

123456789012345 (n columns)
  -15.96 -872.6
  12.489 1723.6

How could I do that with R? Now I have a simple table like this:

x <- data.frame(a= sample(-500.5:500.8,4),
                b= sample(-250.6:420.9,4))
2
  • 1
    The gdata package has a write.fwf function. See stackoverflow.com/a/50499905/2372064`. I'm surprised you didn't find that with google. Commented Feb 18, 2019 at 16:29
  • I'm surprised too, thank you. Commented Feb 18, 2019 at 16:45

2 Answers 2

4

Format it with sprintf (help(sprintf) for more info) and then write the lines out with writeLines. No packages are used.

filename <- stdout() # change to your file name
Lines <- with(x, sprintf("%8.2f%7.1f", a, b))
writeLines(Lines, filename)
##  -212.50  380.4
##   288.50 -220.6
##   -92.50  102.4
##   381.50  346.4

The second line could alternately be written:

Lines <- do.call("sprintf", c("%8.2f%7.1f", x))
Sign up to request clarification or add additional context in comments.

Comments

4

Here is a more automated version using Grothendieck's answer

https://gist.github.com/haozhu233/28d1309b58431f4929f78243054f1f58

#' Generate fixed width file in R
#' @description This simple function creates fixed width file with no 
#' extra dependencies. 
#' @param justify "l", "r" or something like "lrl" for left, right, left. 
#' @examples dt <- data.frame(a = 1:3, b = NA, c = c('a', 'b', 'c'))
#' write_fwf(dt, "test.txt", width = c(4, 4, 3))
#' @export
write_fwf = function(dt, file, width, 
                     justify = "l", replace_na = "NA") {
  fct_col = which(sapply(dt, is.factor))
  if (length(fct_col) > 0) {
    for (i in fct_col) {
      dt[,i] <- as.character(dt[,i])
    }
  }
  dt[is.na(dt)] = replace_na
  n_col = ncol(dt)
  justify = unlist(strsplit(justify, ""))
  justify = as.character(factor(justify, c("l", "r"), c("-", "")))
  if (n_col != 1) {
    if (length(width) == 1) width = rep(width, n_col)
    if (length(justify) == 1) justify = rep(justify, n_col)
  }
  sptf_fmt = paste0(
    paste0("%", justify, width, "s"), collapse = ""
  )
  tbl_content = do.call(sprintf, c(fmt = sptf_fmt, dt))
  tbl_header = do.call(sprintf, c(list(sptf_fmt), names(dt)))
  out = c(tbl_header, tbl_content)
  writeLines(out, file)
}

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.