Заменить несколькими элементами в столбце в зависимости от условия - PullRequest
4 голосов
/ 04 марта 2020

У меня возникли некоторые проблемы при замене значения в столбце фрейма данных.

У меня есть два фрейма данных, которые выглядят так:

таблица результатов:

r <- data.frame(d = c("100", "100,111", "100,111,123"), r = c("3", "3,6,7", "42,57"))

таблица сопоставления:

m <- data.frame(id = c("3", "6", "7", "42", "57", "100", "111", "123"), name= c("tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7", "tc8"))

Теперь я хочу, чтобы строки в m$name заменяли числа в r$d и r$r на основе совпадения / частичного совпадения в m$id, для меня сложная часть, что могут появиться несколько чисел.

Пример: кортеж «100,111» «3,6,7» должен быть «tc6, tc7», «tc1, tc2, tc3» в конце.

Любая помощь будет высоко оценена .

Ответы [ 5 ]

4 голосов
/ 04 марта 2020

gsubfn заменит каждое совпадение с шаблоном в первом аргументе, заменив это совпадение значением, соответствующим этому имени в списке, указанном во втором аргументе. Мы lapply, что для каждого столбца r.

library(gsubfn)

L <- with(m, as.list(setNames(as.character(name), id)))
replace(r, TRUE, lapply(r, function(x) gsubfn("\\d+", L, as.character(x)))

дает:

            d           r
1         tc6         tc1
2     tc6,tc7 tc1,tc2,tc3
3 tc6,tc7,tc8     tc4,tc5

Примечание

Если столбцы r и m были бы символом, а не фактором, тогда мы могли бы немного упростить это.

m[] <- lapply(m, as.character)
r[] <- lapply(r, as.character)

L <- with(m, as.list(setNames(name, id)))
r[] <- lapply(r, gsubfn, pattern = "\\d+", replacement = L)

или использовать это для последней строки, если вы хотите сохранить ввод r

replace(r, TRUE, lapply(r, gsubfn, pattern = "\\d+", replacement = L))
3 голосов
/ 04 марта 2020

Вот один вкладыш, использующий базу R,

r[] <- lapply(r, function(i) sapply(strsplit(as.character(i), ','), 
                                function(j)paste(m$name[match(j, m$id)], collapse = ',')))

, который дает,

            d           r
1         tc6         tc1
2     tc6,tc7 tc1,tc2,tc3
3 tc6,tc7,tc8     tc4,tc5
2 голосов
/ 04 марта 2020

A tidyverse можно получить столбец в длинном формате, разделить строки на запятую, group_by на каждую строку и столбец и создать строку, разделенную запятыми. Наконец, мы снова получаем данные в широком формате.

library(dplyr)
library(tidyr)

r %>%
  mutate(row = row_number()) %>%
  pivot_longer(cols = -row, values_to = 'id') %>%
  separate_rows(id, sep = ",", convert = TRUE)  %>%
  left_join(m %>% 
             type.convert(as.is = TRUE), by = 'id')  %>%
  group_by(row, name.x)  %>%
  summarise(name = toString(name.y)) %>%
  pivot_wider(names_from = name.x, values_from = name) %>%
  ungroup %>%
  select(-row)

# A tibble: 3 x 2
#  d             r            
#  <chr>         <chr>        
#1 tc6           tc1          
#2 tc6, tc7      tc1, tc2, tc3
#3 tc6, tc7, tc8 tc4, tc5     
1 голос
/ 04 марта 2020

Предлагаемое решение с использованием базы R:

r <- data.frame(d = c("100", "100,111", "100,111,123"), r = c("3", "3,6,7", "42,57"))
m <- data.frame(id = c("3", "6", "7", "42", "57", "100", "111", "123"), name= c("tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7", "tc8"))

Преобразование коэффициентов в символ:

m <- apply(m, 2, as.character)
r <- apply(r, 2, as.character)

L oop через каждую ячейку и замена элементов кортежей с помощью m:

result <- r
for (i in seq_along(r[, 1])) {
  for (j in seq_along(r[1, ])) {
    result[i, j] <- paste0(sapply(strsplit(r[i, j], ","), function(x) m[m[, 1] %in% x, 2]), collapse=", ")
  }
}

result сейчас:

     d               r              
[1,] "tc6"           "tc1"          
[2,] "tc6, tc7"      "tc1, tc2, tc3"
[3,] "tc6, tc7, tc8" "tc4, tc5"
1 голос
/ 04 марта 2020

Вот базовый способ R сделать это, используя функции apply. Мы можем использовать lapply в столбцах d и r (показан только код для d), а затем перебирать фрейм данных терминов с заменами. Затем мы вызываем sub для каждого найденного термина / замены.

r$d <- lapply(r$d, function(x) {
    apply(m, 1, function(y) {
        x <<- gsub(paste0("\\b", y[1], "\\b"), y[2], x)
    })
    return(x)
})
r

               d     r
1         tc6     3
2     tc6,tc7 3,6,7
3 tc6,tc7,tc8 42,57

Данные:

r <- data.frame(d = c("100", "100,111", "100,111,123"), r = c("3", "3,6,7", "42,57"), stringsAsFactors=FALSE)
m <- data.frame(id = c("3", "6", "7", "42", "57", "100", "111", "123"), name= c("tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7", "tc8"))

Обратите внимание, что с помощью родительского назначения области видимости <<- оператор часто злой, но в этом случае я использую его для ссылки на область действия, определенную во внешнем вызове lapply, поэтому, возможно, это более приемлемо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...