-1

I have a data like below;

data<-list(X2019 = structure(1:14, .Label = c(" 0.439", " 0.877", " 1.316", 
" 2.305", " 3.903", " 7.552", "11.328", "14.034", "16.770", "17.787", 
"23.544", "27.241", "28.037", "38.508"), class = "factor"), X2020 = structure(1:14, .Label = c(" 0.962000", 
" 1.708000", " 2.201333", " 3.626111", " 6.061444", " 9.514000", 
"11.430889", "12.548556", "13.827000", "15.139333", "17.439667", 
"21.050333", "24.804444", "28.883333"), class = "factor"), X2021 = structure(1:14, .Label = c(" 1.466750", 
" 2.755625", " 3.940125", " 6.700750", "10.619125", "13.989750", 
"17.152250", "17.721125", "21.121625", "23.826625", "24.970000", 
"25.686375", "31.951125", "32.904875"), class = "factor"), X2022 = structure(1:14, .Label = c(" 1.316143", 
" 2.393143", " 3.222143", " 4.903429", " 6.907571", "10.248714", 
"11.352000", "13.680286", "14.364286", "14.797000", "17.181000", 
"19.829571", "20.797714", "25.384429"), class = "factor"), X2023 = structure(1:14, .Label = c(" 1.717000", 
" 3.274571", " 4.711857", " 7.307571", "11.694429", "17.294571", 
"20.463000", "20.948143", "22.685429", "22.718714", "25.589286", 
"29.122857", "29.790429", "32.740857"), class = "factor"), X2024 = structure(1:14, .Label = c(" 1.654000", 
" 2.559857", " 3.088143", " 4.371143", " 6.263286", " 8.821286", 
" 8.857000", "10.344714", "10.799286", "12.797571", "12.941286", 
"12.967000", "13.844429", "14.242429"), class = "factor")) 

data

As you can see element types are factor.

But I want to convert them to double.

out<-list(`2019` = c(0.439, 0.877, 1.316, 2.305, 3.903, 7.552, 11.328, 
14.034, 17.787, 16.77, 23.544, 28.037, 27.241, 38.508), `2020` = c(0.962, 
1.708, 2.20133333333333, 3.62611111111111, 6.06144444444444, 
9.514, 11.4308888888889, 12.5485555555556, 13.827, 15.1393333333333, 
17.4396666666667, 21.0503333333333, 24.8044444444444, 28.8833333333333
), `2021` = c(1.46675, 2.755625, 3.940125, 6.70075, 10.619125, 
13.98975, 17.15225, 17.721125, 23.826625, 21.121625, 25.686375, 
24.97, 31.951125, 32.904875), `2022` = c(1.31614285714286, 2.39314285714286, 
3.22214285714286, 4.90342857142857, 6.90757142857143, 10.2487142857143, 
11.352, 13.6802857142857, 14.797, 14.3642857142857, 17.181, 19.8295714285714, 
20.7977142857143, 25.3844285714286), `2023` = c(1.717, 3.27457142857143, 
4.71185714285714, 7.30757142857143, 11.6944285714286, 17.2945714285714, 
20.463, 20.9481428571429, 22.6854285714286, 25.5892857142857, 
22.7187142857143, 29.7904285714286, 29.1228571428571, 32.7408571428571
), `2024` = c(1.654, 2.55985714285714, 3.08814285714286, 4.37114285714286, 
6.26328571428571, 8.857, 8.82128571428571, 10.3447142857143, 
10.7992857142857, 12.7975714285714, 12.9412857142857, 13.8444285714286, 
12.967, 14.2424285714286))

enter image description here

I tried as.numeric, as.characteristic codes but I got errors.

I need to see my elements as double.

Community
  • 1
  • 1
  • 5
    https://cran.r-project.org/doc/FAQ/R-FAQ.html#How-do-I-convert-factors-to-numeric_003f – jogo Jun 05 '20 at 13:10

5 Answers5

4

in base R, there is a function called type.convert. Use this function as shown below:

(dat1 <- type.convert(data))

$X2019
 [1]  0.439  0.877  1.316  2.305  3.903  7.552 11.328 14.034 16.770 17.787 23.544
[12] 27.241 28.037 38.508

$X2020
 [1]  0.962000  1.708000  2.201333  3.626111  6.061444  9.514000 11.430889
 [8] 12.548556 13.827000 15.139333 17.439667 21.050333 24.804444 28.883333
  :
  :

looking at the structure of the result obtained from running type.convert:

str(dat1)
List of 6
 $ X2019: num [1:14] 0.439 0.877 1.316 2.305 3.903 ...
 $ X2020: num [1:14] 0.962 1.708 2.201 3.626 6.061 ...
 $ X2021: num [1:14] 1.47 2.76 3.94 6.7 10.62 ...
 $ X2022: num [1:14] 1.32 2.39 3.22 4.9 6.91 ...
 $ X2023: num [1:14] 1.72 3.27 4.71 7.31 11.69 ...
 $ X2024: num [1:14] 1.65 2.56 3.09 4.37 6.26 ...
Onyambu
  • 67,392
  • 3
  • 24
  • 53
1

you can use as.character to translate into text andparse_number to translate text into a number

library(tidyverse)
out <- map(data, ~ parse_number(as.character(.x)))
Yuriy Saraykin
  • 8,390
  • 1
  • 7
  • 14
1

In one step using base R and with Jogo's faq in mind. This assumes there aren't any other items in the list


newdata <- lapply(data, function (x) as.numeric(as.character(x)))
newdata
#> $X2019
#>  [1]  0.439  0.877  1.316  2.305  3.903  7.552 11.328 14.034 16.770 17.787
#> [11] 23.544 27.241 28.037 38.508
#> 
#> $X2020
#>  [1]  0.962000  1.708000  2.201333  3.626111  6.061444  9.514000 11.430889
#>  [8] 12.548556 13.827000 15.139333 17.439667 21.050333 24.804444 28.883333
#> 
#> $X2021
#>  [1]  1.466750  2.755625  3.940125  6.700750 10.619125 13.989750 17.152250
#>  [8] 17.721125 21.121625 23.826625 24.970000 25.686375 31.951125 32.904875
#> 
#> $X2022
#>  [1]  1.316143  2.393143  3.222143  4.903429  6.907571 10.248714 11.352000
#>  [8] 13.680286 14.364286 14.797000 17.181000 19.829571 20.797714 25.384429
#> 
#> $X2023
#>  [1]  1.717000  3.274571  4.711857  7.307571 11.694429 17.294571 20.463000
#>  [8] 20.948143 22.685429 22.718714 25.589286 29.122857 29.790429 32.740857
#> 
#> $X2024
#>  [1]  1.654000  2.559857  3.088143  4.371143  6.263286  8.821286  8.857000
#>  [8] 10.344714 10.799286 12.797571 12.941286 12.967000 13.844429 14.242429

Based on your data

data <- list(X2019 = structure(1:14, .Label = c(" 0.439", " 0.877", " 1.316",
" 2.305", " 3.903", " 7.552", "11.328", "14.034", "16.770", "17.787",
"23.544", "27.241", "28.037", "38.508"), class = "factor"), X2020 = structure(1:14, .Label = c(" 0.962000",
" 1.708000", " 2.201333", " 3.626111", " 6.061444", " 9.514000",
"11.430889", "12.548556", "13.827000", "15.139333", "17.439667",
"21.050333", "24.804444", "28.883333"), class = "factor"), X2021 = structure(1:14, .Label = c(" 1.466750",
" 2.755625", " 3.940125", " 6.700750", "10.619125", "13.989750",
"17.152250", "17.721125", "21.121625", "23.826625", "24.970000",
"25.686375", "31.951125", "32.904875"), class = "factor"), X2022 = structure(1:14, .Label = c(" 1.316143",
" 2.393143", " 3.222143", " 4.903429", " 6.907571", "10.248714",
"11.352000", "13.680286", "14.364286", "14.797000", "17.181000",
"19.829571", "20.797714", "25.384429"), class = "factor"), X2023 = structure(1:14, .Label = c(" 1.717000",
" 3.274571", " 4.711857", " 7.307571", "11.694429", "17.294571",
"20.463000", "20.948143", "22.685429", "22.718714", "25.589286",
"29.122857", "29.790429", "32.740857"), class = "factor"), X2024 = structure(1:14, .Label = c(" 1.654000",
" 2.559857", " 3.088143", " 4.371143", " 6.263286", " 8.821286",
" 8.857000", "10.344714", "10.799286", "12.797571", "12.941286",
"12.967000", "13.844429", "14.242429"), class = "factor"))

Chuck P
  • 3,862
  • 3
  • 9
  • 20
-1

I am not sure what code you've tried, or what errors you get, but when I run the following code, I get numeric (which I think is the same as double):

data$X2019<-as.character(data$X2019)
data$X2019<-as.double(data$X2019)  #as.double does the same as as.numeric here
class(data$X2019)
[1] "numeric"

Usually you have to take a factor to character first, and then to numeric, because factors have dummy coding that can cause problems. What I mean by that is a factor called "FactorA" might be coded as 1, whereas "FactorB" might be coded as 2 "under the hood" so to speak. So factor straight to numeric can cause problems. If you want to do it to the whole list, this works for me:

data[]<-lapply(data[],as.character) ## you can specify certain vectors (lists or columns of a dataframe here, so that not all of the data is converted to a different class
data[]<-lapply(data[],as.numeric)

lapply(data,class)

$X2019
[1] "numeric"

$X2020
[1] "numeric"

$X2021
[1] "numeric"

$X2022
[1] "numeric"

$X2023
[1] "numeric"

$X2024
[1] "numeric"

a sample vector:

data$X2019
 [1]  0.439  0.877  1.316  2.305  3.903  7.552 11.328 14.034 16.770 17.787 23.544 27.241 28.037 38.508
Dylan_Gomes
  • 2,066
  • 14
  • 29
  • I didn't downvote, but I'd think it might be preferred to do one lapply with `as.numeric(as.character(.))` instead of two lapplys ... it's not a big deal to me, but it does seem a little double-tappy. \*shrug\* (I agree that it can be frustrating to get no-comment downvotes, but .. almost every downvote I've received has been anonymous.) – r2evans Jun 05 '20 at 17:16
  • Thanks for the comment @r2evans. Yes I know that there was a much more concise way to write the answer, I just try to make it an opportunity for learning. With such a simple question, it seemed that the OP was relatively new to R, so explaining a solution in longer steps made sense to me. IMO, that does not detract from an answer or is a reason for a downvote, but that isn't my call to make.. – Dylan_Gomes Jun 06 '20 at 18:36
-5

UPDATE:

You need to apply as.numeric() to levels(). Weirdly enough, you have coded real values in the levels and not the other way around.

So, let's define the initial list called data.

data<-list(X2019 = structure(1:14, 
                             .Label = c(" 0.439", " 0.877", " 1.316", 
                                        " 2.305", " 3.903", " 7.552", "11.328", "14.034", "16.770", "17.787", 
                                        "23.544", "27.241", "28.037", "38.508"), 
                             class = "factor"), 
           X2020 = structure(1:14, .Label = c(" 0.962000", 
                                              " 1.708000", " 2.201333", " 3.626111", " 6.061444", " 9.514000", 
                                              "11.430889", "12.548556", "13.827000", "15.139333", "17.439667", 
                                              "21.050333", "24.804444", "28.883333"), 
                             class = "factor"), 
           X2021 = structure(1:14, .Label = c(" 1.466750", 
                                              " 2.755625", " 3.940125", " 6.700750", "10.619125", "13.989750", 
                                              "17.152250", "17.721125", "21.121625", "23.826625", "24.970000", 
                                              "25.686375", "31.951125", "32.904875"), 
                             class = "factor"), 
           X2022 = structure(1:14, 
                             .Label = c(" 1.316143", 
                                        " 2.393143", " 3.222143", " 4.903429", " 6.907571", "10.248714", 
                                        "11.352000", "13.680286", "14.364286", "14.797000", "17.181000", 
                                        "19.829571", "20.797714", "25.384429"), 
                             class = "factor"), 
           X2023 = structure(1:14, 
                             .Label = c(" 1.717000", 
                                        " 3.274571", " 4.711857", " 7.307571", "11.694429", "17.294571", 
                                        "20.463000", "20.948143", "22.685429", "22.718714", "25.589286", 
                                        "29.122857", "29.790429", "32.740857"), 
                             class = "factor"), 
           X2024 = structure(1:14, 
                             .Label = c(" 1.654000", 
                                        " 2.559857", " 3.088143", " 4.371143", " 6.263286", " 8.821286", 
                                        " 8.857000", "10.344714", "10.799286", "12.797571", "12.941286", 
                                        "12.967000", "13.844429", "14.242429"), 
                             class = "factor")) 

Now, if we check each element's class with lapply(), we can confirm that are all factor. Since you have the real values being put in the levels of the factor, you need two steps to achieve what you want.

First, extract the levels out of each element of data with levels(). Then, immediately cast the character vector which levels() returns to your desired numeric with as.numeric().

Because you have a list, the easiest way to do this is through lapply(). Also, because you need two steps, you cannot just call the two functions so we need a simple anonymous function within lapply() which only takes the argument x.

lapply(data, class)
#> $X2019
#> [1] "factor"
#> 
#> $X2020
#> [1] "factor"
#> 
#> $X2021
#> [1] "factor"
#> 
#> $X2022
#> [1] "factor"
#> 
#> $X2023
#> [1] "factor"
#> 
#> $X2024
#> [1] "factor"
data_num <- lapply( data, function(x) as.numeric(levels(x)) )

lapply(data_num, class)
#> $X2019
#> [1] "numeric"
#> 
#> $X2020
#> [1] "numeric"
#> 
#> $X2021
#> [1] "numeric"
#> 
#> $X2022
#> [1] "numeric"
#> 
#> $X2023
#> [1] "numeric"
#> 
#> $X2024
#> [1] "numeric"

data_num
#> $X2019
#>  [1]  0.439  0.877  1.316  2.305  3.903  7.552 11.328 14.034 16.770 17.787
#> [11] 23.544 27.241 28.037 38.508
#> 
#> $X2020
#>  [1]  0.962000  1.708000  2.201333  3.626111  6.061444  9.514000 11.430889
#>  [8] 12.548556 13.827000 15.139333 17.439667 21.050333 24.804444 28.883333
#> 
#> $X2021
#>  [1]  1.466750  2.755625  3.940125  6.700750 10.619125 13.989750 17.152250
#>  [8] 17.721125 21.121625 23.826625 24.970000 25.686375 31.951125 32.904875
#> 
#> $X2022
#>  [1]  1.316143  2.393143  3.222143  4.903429  6.907571 10.248714 11.352000
#>  [8] 13.680286 14.364286 14.797000 17.181000 19.829571 20.797714 25.384429
#> 
#> $X2023
#>  [1]  1.717000  3.274571  4.711857  7.307571 11.694429 17.294571 20.463000
#>  [8] 20.948143 22.685429 22.718714 25.589286 29.122857 29.790429 32.740857
#> 
#> $X2024
#>  [1]  1.654000  2.559857  3.088143  4.371143  6.263286  8.821286  8.857000
#>  [8] 10.344714 10.799286 12.797571 12.941286 12.967000 13.844429 14.242429

Created on 2020-06-05 by the reprex package (v0.3.0)

Francesco Grossetti
  • 1,555
  • 9
  • 17
  • 3
    Nope. You should check your output, all vectors of the list are turned into `1:14`. If you read the FAQ (R FAQ 7.10) that jogo provided, it says *"do not call as.numeric() or their likes directly"*. – r2evans Jun 05 '20 at 13:21
  • There are often many issues going straight from a factor to numeric because of dummy coding. – Dylan_Gomes Jun 05 '20 at 13:23
  • @r2evans pls check my updated answer. Now that should be good. – Francesco Grossetti Jun 05 '20 at 13:24
  • This would look intimidating to someone new to programming/R. You should consider breaking up your code chunk as your answer is buried and not well explained. – Daniel O Jun 05 '20 at 13:25
  • Still no, but for a different reason: the numbers are just the unique levels, not the order or frequency that might have been in the original data. Try `vec <- rep(factor(runif(3)), each=2)`, look at `vec`, then run `as.character(levels(vec))`. – r2evans Jun 05 '20 at 13:30
  • The FAQ does include something that starts with that code, but you missed the indexing at the end: `[as.integer(x)]`, making it `lapply(d, function(x) as.numeric(levels(x))[as.integer(x)])`. – r2evans Jun 05 '20 at 13:31