I have a bunch of nested lists that arrive with all character-typed elements. Some of these characters are in fact numbers that need to be converted to numeric-typed elements.
How can I modify these lists so that all possible character-typed numbers are converted to numeric, but the non-number character elements remain intact (e.g., aren't converted to NA
by as.numeric()
)?
For example, I start with
raw_list <- list(
'a' = list('1', '2'),
'b' = list(
'c' = list('3', 'x'),
'd' = c('4', 'z'),
'e' = '5'))
But I need to get to
cleaned_list <- list(
'a' = list(1, 2),
'b' = list(
'c' = list(3, 'x'),
'd' = c(4, 'z'),
'e' = 5))
Bonus: Extra gratitudie for tidyverse/purrr-based solutions
CodePudding user response:
Another option is to use type.convert
, which can take lists as arguments.
raw_list %>%
type.convert(as.is = TRUE)
This would be the same as using purrr
with type.convert
.
library(purrr)
purrr::map(raw_list, type.convert, as.is = TRUE)
Output
$a
$a[[1]]
[1] 1
$a[[2]]
[1] 2
$b
$b$c
$b$c[[1]]
[1] 3
$b$c[[2]]
[1] "x"
$b$d
[1] "4" "z"
$b$e
[1] 5
CodePudding user response:
You can use readr::parse_guess
to convert character-typed numbers to numeric-typed numbers without converting characters to NA
s.
I also created a function to convert the numbers in a nested list. Please note that you cannot store characters and numerics in the same vector.
I hope this would help you.
library(tidyverse)
func_parse_list <- function(l){
if(length(l)>1){
map(l, func_parse_list) %>% return()
}else{
parse_guess(l) %>% return()
}
}
list('a' = list('1', '2'),
'b' = list(
'c' = list('3', 'x'),
'd' = c('4', 'z'),
'e' = '5')) %>%
func_parse_list()
#> $a
#> $a[[1]]
#> [1] 1
#>
#> $a[[2]]
#> [1] 2
#>
#>
#> $b
#> $b$c
#> $b$c[[1]]
#> [1] 3
#>
#> $b$c[[2]]
#> [1] "x"
#>
#>
#> $b$d
#> $b$d[[1]]
#> [1] 4
#>
#> $b$d[[2]]
#> [1] "z"
#>
#>
#> $b$e
#> [1] 5
Created on 2021-12-05 by the reprex package (v2.0.1)