0

I have several dataframes in my dataset that contain numeric values, but are type chr. They look like this:

   IDs     FCC_Faces FCNC_Faces          FCC_Objects         FCNC_Objects  FCC_Scenes FCNC_Scenes FCC_Words  FCNC_Words    Age Group
   <chr>       <dbl> <chr>               <chr>               <chr>         <chr>      <chr>       <chr>      <chr>       <dbl> <dbl>
 1 CON_L01      1    0.58330000000000004 0.83330000000000004 0.5833000000~ 0.6        0.6         0.9165999~ 0.66659999~    63     0
 2 CON_L03      0.92 0.83                1                   0.92          0.9        0.9         0.83       1              37     0
 3 CON_L04      0.75 0.83                0.92                0.92          0.9        0.8         0.67       0.92           48     0
 4 CON_L05      0.75 1                   0.92                1             0.9        1           1          1              49     0
 5 CON_L07      0.58 0.17                0.57999999999999996 0.75          0.8        0.7         0.83       0.67           69     0
 6 CON_L10      0.92 0.67                0.83                0.5799999999~ 0.8        0.9         0.33       0.57999999~    58     0
 7 CON_L14      0.83 0.83                0.83                0.75          0.8        0.9         0.92       0.67           62     0
 8 CON_L16      1    0.92                NA                  NA            0.9        0.9         1          1              40     0
 9 CON_L17      0.83 0.57999999999999996 0.75                0.83          0.9        0.6         1          0.83           48     0
10 CON_L18      0.75 0.75                0.75                0.75          0.9        0.5         0.75       0.67           55     0
# ... with 70 more rows

I wanted to write a function to which I could pass the dataframe, the column names, and have it convert all of them to numeric. My first attempt was just using lapply():

cols_to_numeric <- function(dframe, columns) {
    dframe[ , columns] <- lapply(dframe[ , columns], numeric)
    return(dframe)
}

However, I get this error:

Error in FUN(X[[i]], ...) : invalid 'length' argument 
3.
FUN(X[[i]], ...) 
2.
lapply(dframe[, columns], numeric)

So, looking for another solution, this thread suggested a nice approach using Tidyverse:

cols_to_numeric <- function(dframe, columns) {
    require(magrittr)
    require(tidyverse)
    
    dframe %<>% mutate_at(columns, numeric)
    return(dframe)
}

But I get a very similar error:

 Error: Problem with `mutate()` input `FCC_Faces`.
x invalid 'length' argument
i Input `FCC_Faces` is `(function (length = 0L) ...`.

But the length of this variable is very clearly not zero:

> length(CON_data$FCC_Faces)
[1] 80

Further, if I just do the coercion for each column manually, it works without complaints:

> CON_data$FCC_Faces <- as.numeric(CON_data$FCC_Faces)

> str(CON_data)
'data.frame':   80 obs. of  11 variables:
 $ IDs         : chr  "CON_L01" "CON_L03" "CON_L04" "CON_L05" ...
 $ FCC_Faces   : num  1 0.92 0.75 0.75 0.58 0.92 0.83 1 0.83 0.75 ...
 $ FCNC_Faces  : chr  "0.58330000000000004" "0.83" "0.83" "1" ...
 $ FCC_Objects : chr  "0.83330000000000004" "1" "0.92" "0.92" ...
 $ FCNC_Objects: chr  "0.58330000000000004" "0.92" "0.92" "1" ...
 $ FCC_Scenes  : chr  "0.6" "0.9" "0.9" "0.9" ...
 $ FCNC_Scenes : chr  "0.6" "0.9" "0.8" "1" ...
 $ FCC_Words   : chr  "0.91659999999999997" "0.83" "0.67" "1" ...
 $ FCNC_Words  : chr  "0.66659999999999997" "1" "0.92" "1" ...
 $ Age         : num  63 37 48 49 69 58 62 40 48 55 ...
 $ Group       : num  0 0 0 0 0 0 0 0 0 0 ...
> 

What on earth am I doing wrong here? I don't want to have to manually coerce every single column for each dataframe every time I make any changes.

8
  • 1
    Does mutate_if(is.character, as.numeric) work? Commented Apr 15, 2022 at 9:28
  • Or mutate(across(c("var1", "var"), as.numeric))? Commented Apr 15, 2022 at 9:30
  • I had just come across this myself, thank you! CON_data %>% mutate(across(colnames(CON_data)[2:9]), as.numeric) unfortunately yields the error: Error: Problem with mutate()` input ..2. x Input ..2 must be a vector, not a primitive function. i Input ..2 is as.numeric.` Commented Apr 15, 2022 at 9:31
  • Did you try @PaulS solution? Commented Apr 15, 2022 at 9:32
  • 1
    @Rowan note the position of your closing bracket. as.numeric should be inside across(). Also, just across(2:9, as.numeric) is enough, you don't need colnames. Commented Apr 15, 2022 at 9:39

2 Answers 2

1

A possible solution:

library(dplyr)

df <- tibble(
  x = c("0.2", "0.4", "0.9"), 
  y = c("1.2", "2.4", "3.9"))

df %>% 
  mutate(across(x:y, as.numeric))
#> # A tibble: 3 × 2
#>       x     y
#>   <dbl> <dbl>
#> 1   0.2   1.2
#> 2   0.4   2.4
#> 3   0.9   3.9
Sign up to request clarification or add additional context in comments.

1 Comment

I mentioned in the above comments, but this unfortunately gives me the error: > CON_data <- CON_data %>% mutate(across(FCC_Faces:FCNC_Words), as.numeric) Error: Problem with mutate()` input ..2. x Input ..2 must be a vector, not a primitive function. i Input ..2 is as.numeric.`
1

Just use type.convert function from base R:

type.convert(dframe, as.is = TRUE)

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.