Преобразование символьных чисел в числовые во вложенном списке со смешанными типами в R

#r #iteration #nested-lists #type-coercion

#r #итерация #вложенные списки #тип-принуждение

Вопрос:

У меня есть куча вложенных списков, которые поступают со всеми элементами, набранными символами. Некоторые из этих символов на самом деле являются числами, которые необходимо преобразовать в элементы с числовым типом.

Как я могу изменить эти списки так, чтобы все возможные символьные числа преобразовывались в числовые, но не числовые символьные элементы оставались нетронутыми (например, не преобразовывались в NA by as.numeric() )?

Например, я начинаю с

 raw_list <- list(
      'a' = list('1', '2'),
      'b' = list(
        'c' = list('3', 'x'),
        'd' = c('4', 'z'),
        'e' = '5'))
 

Но мне нужно добраться до

 cleaned_list <- list(
      'a' = list(1, 2),
      'b' = list(
        'c' = list(3, 'x'),
        'd' = c('4', 'z'),
        'e' = 5))
 

Бонус: дополнительная благодарность за решения на основе tidyverse / purrr

Комментарии:

1. Не e должно быть 5 в raw_list ?

2. Вы правы, я изменил входные и выходные данные, чтобы они соответствовали

3. Я не понимаю. Есть ли что-то, что я должен сделать с этой ссылкой?

Ответ №1:

Другой вариант — использовать type.convert , который может принимать списки в качестве аргументов.

 raw_list %>%
  type.convert(as.is = TRUE)
 

Это будет то же самое, что и при использовании purrr with type.convert .

 library(purrr)

purrr::map(raw_list, type.convert, as.is = TRUE)
 

Вывод

 $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
 

Комментарии:

1. purrr В этом случае вам не нужно. type.convert() может принимать списки в качестве аргумента. Итак: raw_list %>% type.convert(as.is = TRUE) то же самое, что и с purrr .

2. Обратите внимание, что решение tjis по-прежнему сохраняет 4 в элементе d в качестве символа.

3. @deschen. Также map есть решение. $d [1] "4" "z" должно быть символьным в соответствии с правилами атомарных векторов ?! Или я что-то упускаю?

4. Правильно. Не уделял достаточно пристального внимания. У вас не может быть символов и чисел в одном векторе.

5. Вы все правы в 'd' = c('4', 'z') том, что число 4 должно оставаться символом, поскольку оно является частью атомарного вектора. Я пересмотрел вопрос и cleaned_list выходные данные, чтобы отразить это.

Ответ №2:

Вы можете использовать readr::parse_guess для преобразования символьных чисел в числовые числа без преобразования символов в NA s.

Я также создал функцию для преобразования чисел во вложенном списке. Пожалуйста, обратите внимание, что вы не можете хранить символы и цифры в одном векторе.

Я надеюсь, что это поможет вам.

 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
 

Создано 2021-12-05 пакетом reprex (v2.0.1)