替换数据框的列中的值时遇到一些问题。
我有两个看起来像这样的数据框:
结果表:
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”。
任何帮助将不胜感激。
答案 0 :(得分:4)
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))
答案 1 :(得分:3)
这里是一个使用底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 :(得分:2)
一种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
答案 3 :(得分:1)
这是使用apply
函数的基本R方式。我们可以在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
的外部调用中定义的作用域,所以也许是更可接受。
答案 4 :(得分:1)
使用基数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)
遍历每个单元格,并使用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"