1

I'm trying to use R to print some data in a custom fashion for use in a separate program. It keeps trying to left pad my numbers, and I can't quite get it to stop. I have not been able to find anything in the ?format, ?print, ?cat, ?etc. to quite fix my problem. Also, searching for fixed width or variable width results in people looking to solve somewhat different problems (and most looking to change the style of padding -- not remove it).

Take the following data setup:

> df.play <- data.frame(name = c('a','b','c'), value = c(1,11,111))

> df.play
  name value
1    a     1
2    b    11
3    c   111

This is my desired output

#Goal
> for (j in seq(nrow(df.play))) {cat(as.character(df.play[j,1]),'.',df.play[j,2],'\n',sep='')}
a.1
b.11
c.111

How do I get this output format without explicitly looping (preferably avoiding external libraries)?

#Naive Attempt 1
#    Why does it left pad the second "column"?
#    How do I get it to stop?
#    Why does cat even parse it as a column to begin with?
junk<-apply(df.play,1,function(x) cat(x[1],'.',x[2],'\n',sep=''))
a.  1
b. 11
c.111

#Naive Attempt 2
#    Perhaps this will help provide some insight.
#    The number is a string before it gets to cat. Why?
t<-apply(df.play,1,function(x) cat(x[1],'.',sprintf('%d',x[2]),'\n',sep=''))
 Error in sprintf("%d", x[2]) : 
  invalid format '%d'; use format %s for character objects 

2 Answers2

1

Maybe this will do it:

cat(do.call(paste, c(df.play, list(sep = '.'))), sep = '\n')

# a.1
# b.11
# c.111

In addition, apply by row will give fixed with results because the format will add extra spacing when converting data.frame to matrix with as.matrix (see this post).

Community
  • 1
  • 1
mt1022
  • 16,834
  • 5
  • 48
  • 71
1

You can use sprintf, not sure you wanted sprintf solution though, you just need to put a "-" sign before the total number of chars to make left align, like below:

data.frame(value=sprintf("%-5s",paste0(df.play$name,".",df.play$value)))

Or BaseR solution with gsub:

df <- data.frame(value =gsub("\\s+","",apply(df.play,1,paste0,collapse=".")))
data.frame(value1=sprintf("%-5s",df$value))

Or in case you don't want to paste0 then we can unite also,

df <- tidyr::unite(df.play,value,1:2,sep=".")
data.frame(value1=sprintf("%-5s",df$value))

Output:

value
1 a.1  
2 b.11 
3 c.111
PKumar
  • 10,971
  • 6
  • 37
  • 52