R dataframe в "словарь", избегая списка факторов

У меня есть датафрейм df с двумя столбцами, один из которых содержит имена, а второй - значения, которые могут быть, например, строковыми или двойными

> df
       name   value
1  cat_name    Bart
2   cat_age       5
3  dog_name    Fred
4   dog_age       9
5 total_pet       2

Я хотел бы конвертировать df в list именованных объектов, чтобы я мог позвонить list$cat_name и верни строку "Bart" или же list$bird_age и вернуться 1 как числовой

я пробовал

> list <- split(df[, 2], df[, 1])
> list
$cat_age
[1] 5
Levels: 2 5 9 Bart Fred

$cat_name
[1] Bart
Levels: 2 5 9 Bart Fred

$dog_age
[1] 9
Levels: 2 5 9 Bart Fred

$dog_name
[1] Fred
Levels: 2 5 9 Bart Fred

$total_pet
[1] 2
Levels: 2 5 9 Bart Fred

который превращает df в list факторов. Это почти то, что я хочу, потому что $ Оператор работает нормально. Тем не менее, я не привык работать с факторами, и я хотел бы знать, было ли еще какое -то преобразование данных из списка в список доступных. Раздражающая часть происходит из-за того, что для работы со строками и числами мы должны преобразовать факторы обратно в эти типы

> as.character(list$cat_name)
[1] "Bart"
> as.numeric(as.character(list$total_pet))
[1] 3

Заметив это df[, 1] а также df[, 2] на самом деле факторы, которые я пытался использовать

> list <- split(as.character(df[, 2]), df[, 1])
> list
$cat_age
[1] "5"

$cat_name
[1] "Bart"

$dog_age
[1] "9"

$dog_name
[1] "Fred"

$total_pet
[1] "2"

что почти решает проблему, за исключением того, что числа являются символами, которые будут преобразованы позже. Я также пытался использовать hash объекты

> h <- hash(as.vector(df[, 1]), as.vector(df[, 2]))
> l = as.list(h)
> l
$dog_age
[1] "9"

$dog_name
[1] "Fred"

$cat_age
[1] "5"

$total_pet
[1] "2"

$cat_name
[1] "Bart"

но у меня такой же результат.

У кого-нибудь есть совет? Я что-то упускаю из виду?

Танки:)

2 ответа

Решение

Мы можем сделать это с type.convert

library(purrr)
map(list, type.convert, as.is = TRUE)
#$cat_age
#[1] 5

#$cat_name
#[1] "Bart"

#$dog_age
#[1] 9

#$dog_name
#[1] "Fred"

#$total_pet
#[1] 2

Поскольку это может быть более эффективным путем параллельной реализации, один из вариантов future_map от furrr

library(furrr)
plan(multiprocess)
future_map(list, type.convert, as.is = TRUE)

Базовый подход R...

df[,]<- lapply(df, as.character) # changing factors to character
list <- split(df[, 2], df[, 1])  # Split df just as you did.

list2 <- lapply(list, function(x) {
  y <- regmatches(x, regexpr("\\d", x));
  z <-ifelse(length(y)!=0, as.numeric(y), x);
  z
})

$cat_age
[1] 5

$cat_name
[1] "Bart"

$dog_age
[1] 9

$dog_name
[1] "Fred"

$total_pet
[1] 2

Проверка класса:

> sapply(list2, class)
    cat_age    cat_name     dog_age    dog_name   total_pet 
  "numeric" "character"   "numeric" "character"   "numeric" 

Ваши данные:

df <- read.table(text="      name   value
1  cat_name    Bart
                 2   cat_age       5
                 3  dog_name    Fred
                 4   dog_age       9
                 5 total_pet       2", header=TRUE)
Другие вопросы по тегам