Суммируйте символы из строки с помощью таблицы подстановки в R

#r

Вопрос:

У меня есть фрейм данных поиска (df1), подобный этому:

 col1 col2
A 71
R 156
N 114
D 115
...
 

и у меня есть фрейм данных (df2), содержащий столбец строк, подобных этому:

 [1] "AARA"                       
[2] "DDNRRRNRAAN"                      
[3] "RNDARANDRN"
...
 

Я хотел бы создать новый столбец в df2, который для каждой строки просматривает серию соответствующих чисел из df1 и суммирует их. Таким образом, первая строка в новом столбце df2 будет иметь значение 369 (= 71 71 156 71). Как я мог справиться с этой задачей?

Ответ №1:

Еще одна tidyverse стратегия

 lookup <- structure(list(col1 = c("A", "R", "N", "D"), col2 = c(71L, 156L, 
                                                             114L, 115L)), class = "data.frame", row.names = c(NA, -4L))

df <- structure(list(col = c("AARA", "DDNRRRNRAAN", "RNDARANDRN")),
                 class = "data.frame", row.names = c(NA, -3L))

library(tidyverse)

df %>%
  mutate(SUM = map_dbl(str_split(col, ''), ~ sum(lookup$col2[match(.x, lookup$col1)])))

#>           col  SUM
#> 1        AARA  369
#> 2 DDNRRRNRAAN 1338
#> 3  RNDARANDRN 1182
 

Создано 2021-06-13 пакетом reprex (v2.0.0)

Ответ №2:

Разделите строку на каждый символ, используйте match , чтобы получить соответствующее значение для каждого символа и суммировать их.

 df2$res <- sapply(strsplit(df2$col, ''), function(x) 
                  sum(df1$col2[match(x, df1$col1)], na.rm = TRUE))
df2

#          col  res
#1        AARA  369
#2 DDNRRRNRAAN 1338
#3  RNDARANDRN 1182
 

Используя ту же логику tidyverse , можно было бы —

 library(dplyr)
library(tidyr)

df2 %>%
  mutate(row = row_number()) %>%
  separate_rows(col, sep = '') %>%
  left_join(df1, by = c('col' = 'col1')) %>%
  group_by(row) %>%
  summarise(col = paste0(col, collapse = ''), 
            col2 = sum(col2, na.rm = TRUE)) %>%
  select(-row)
 

данные

 df1 <- structure(list(col1 = c("A", "R", "N", "D"), col2 = c(71L, 156L, 
114L, 115L)), class = "data.frame", row.names = c(NA, -4L))

df2 <- structure(list(col = c("AARA", "DDNRRRNRAAN", "RNDARANDRN")),
class = "data.frame", row.names = c(NA, -3L))