1

I want to use a list as a simple dictionary to change values when the lookup to the list is not null. I'd expected this to work, but it doesn't;

assoc_values <- list("A" = "GROUP1", "C" = "GROUP1", "B" = "GROUP2", "D" = "GROUP3")
some_data_table[!is.null(assoc_values[[lookup_column]]), "mapped_col" := assoc_values[[lookup_column]]]

It fails with error msg Error: recursive indexing failed at level 2. I've tried other approaches like ifelse(!is.null(assoc_values[[lookup_column]]), ...) but always fails.

below there is a reproducible example:

library(data.table)
assoc_values <- list("A" = "GROUP1", "C" = "GROUP1", "B" = "GROUP2", "D" = "GROUP2")
some_data_table <- data.table('col1' = seq(1, 10), 'lookup_column' = c('A', 'A', 'E', 'B', 'D', 'C', 'A', 'F', 'C', 'T'))
some_data_table[!is.null(assoc_values[[lookup_column]]), "mapped_col" := assoc_values[[lookup_column]]]

2 Answers 2

2

You don't really need a list here since a named vector would do.

library(data.table)
assoc_values <- c("A" = "GROUP1", "C" = "GROUP1", "B" = "GROUP2", "D" = "GROUP2")
some_data_table <- data.table(col1 = seq(1, 10), 
                              lookup_column = c('A', 'A', 'E', 'B', 'D',
                                                'C', 'A', 'F', 'C', 'T'))


some_data_table[, new_col := assoc_values[lookup_column]]
some_data_table[is.na(new_col), new_col := lookup_column]

some_data_table

#    col1 lookup_column new_col
# 1:    1             A  GROUP1
# 2:    2             A  GROUP1
# 3:    3             E       E
# 4:    4             B  GROUP2
# 5:    5             D  GROUP2
# 6:    6             C  GROUP1
# 7:    7             A  GROUP1
# 8:    8             F       F
# 9:    9             C  GROUP1
#10:   10             T       T
Sign up to request clarification or add additional context in comments.

3 Comments

This is exactly what I want, Thanks. I wonder why it works different with list and named vector...
list would return a list output. Unless you explicitly need it I guess you are better off using vector.
yes, actually named vectors works better if lookup_column is modified inplace because, list would erase null, but vector wouldn't
1

The error is to mistake '[' with '[[', see this SO post. The solution is to use assoc_values[lookup_column].

some_data_table[!is.null(assoc_values[lookup_column]), 
                "mapped_col" := assoc_values[lookup_column]]

some_data_table
#    col1 lookup_column mapped_col
# 1:    1             A     GROUP1
# 2:    2             A     GROUP1
# 3:    3             E           
# 4:    4             B     GROUP2
# 5:    5             D     GROUP2
# 6:    6             C     GROUP1
# 7:    7             A     GROUP1
# 8:    8             F           
# 9:    9             C     GROUP1
#10:   10             T           

3 Comments

Thanks for the answer, It turns out that a named vector works better if the lookup_column is the same as mapped_col. For some reason lists erase null values, whereas vectors, don't
@lsmor assoc_values[some_data_table$lookup_column] has several NULL entries named <NA>. Can you give an example of what you are saying in this case? (I know that to delete a list member, assign NULL to it)
given assoc_list and assoc_vector the same as in my question but one is a named list and the other is a named vector. Then this: some_data_table[!is.null(assoc_list[lookup_column]), lookup_column := assoc_list[lookup_column]] produces a different result than this: some_data_table[!is.na(assoc_vector[lookup_column]), lookup_column := assoc_vector[lookup_column]] you can check out that the list version deletes null values, whereas the vector version keeps null as original.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.