#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)