1

I have a dataframe. What I want to achieve is to have a column (representing months) coded on 2 characters (string of length 2) instead of an integer.

Here is a little sample of data :

wifi <- data.frame(replicate(2,8:12))

Which creates a dataframe like this :

   X1  X2
1   8   8
2   9   9
3  10  10
4  11  11
5  12  12

I want to have something like this :

   X1  X2
1   8  08
2   9  09
3  10  10
4  11  11
5  12  12

Here is the function I made :

A <- function(x) {
    if(nchar(x)==1) {
        return(paste0("0",x))
    } else {
        return(x)
    }
}

which seems to work as intended ( A("9") == "09" and A("12") == "12").

I tried this

cbind(wifi[1], lapply(wifi[2], A) )

Here is the result I got, it seems like this function is applied one time for all elements and not for each element.

   X1   X2
1   8   08
2   9   09
3  10  010
4  11  011
5  12  012

Warning message: In if (nchar(x) == 1) { : the condition has length > 1 and only the first element will be used

Someone know I could fix that ?

txemsukr
  • 1,017
  • 1
  • 10
  • 32

2 Answers2

2

You should use the sprintf function instead.

This would apply it to all columns:

sapply(wifi, function(x) sprintf("%02.0f", x))

This only to the second one:

sprintf("%02.0f", wifi$X2)

sprintf is a built-in function to format strings (same as in C) and does exactly what you wanted your A function to do

It's better to use sapply for dataframes.

Pop
  • 12,135
  • 5
  • 55
  • 68
1

I would solve it using sprintf()

A <- function(x) {
  sprintf("%02d", x)
}

wifi[[2]] <- A(wifi[[2]])
wifi
  X1 X2
1  8 08
2  9 09
3 10 10
4 11 11
5 12 12

But what's wrong with the current function?

Almost nothing.

if () {} else {} deals with elements of length 1 and lapply(wifi[2], A) feeds it the whole vector. So you could do this with your original function using different subsetting:

sapply(wifi[[2]], A) 

However, perhaps better to go for the vectorised ifelse() and drop the *apply():

A <- function(x) {
  x <- as.character(x)
  ifelse(nchar(x) == 1, paste0("0", x), x)
}
s_baldur
  • 29,441
  • 4
  • 36
  • 69
  • Thanks a lot for you answer, I have seen this ifelse thing before but now thanks to you I know what it is used for :) – txemsukr Aug 17 '18 at 13:22