dplyr替代plyr::mapvalues的方法(使用字典重编码)

7

plyr::mapvalues可以根据字典重编码向量,即在现有值和替换值的两个匹配向量基础上进行操作。

library(plyr)
data <- c("a", "b", "c", "a")
dict_old <- c("a", "b", "c")
dict_new <- c("Apple", "Banana", "Carrot")
mapvalues(data, dict_old, dict_new)
[1] "Apple"  "Banana" "Carrot" "Apple" 

在dplyr中,可以通过创建一个包含新值的列表,并将旧值分配为列表元素的名称来获得等效结果:
list <- as.list(dict_new)
names(list) <- dict_old
recode(data, !!!list)
[1] "Apple"  "Banana" "Carrot" "Apple" 

然而,我认为这种方法相当笨拙。在tidyverse内有更简洁的方法吗?

3个回答

7

使用 stringr 的一种方法可能是:

str_replace_all(data, setNames(dict_new, dict_old))

[1] "Apple"  "Banana" "Carrot" "Apple" 

与基础的 R 方法相比,str_replace_all 的优点在于它不会将 data 中存在但 dict_old 中不存在的值替换为 NAs。以下是一个简短的示例,可与基础 R 版本进行比较:str_replace_all(c("x","y","z"),setNames(c("a","b"),c("x","y"))) - Paul Rougieux

2
如果你认为使用 !!! 是 "不优雅的",你可以将其隐藏在一个整洁的函数中。这就是我经常编写定制映射的方式:
data <- c("a", "b", "c", "a")

my_map <- function (x) {
  dict_old <- c("a", "b", "c")
  dict_new <- c("Apple", "Banana", "Carrot")
  dict <- setNames(dict_new, dict_old)
  dplyr::recode(data, !!!dict)
}

my_map(data)
[1] "Apple"  "Banana" "Carrot" "Apple" 

我简直不敢相信他们不在dplyr中实现mapvalues()(例如您建议的那样),因为它是一个完美的函数,许多人都在使用。而且实际上我不理解"!!!"是什么意思,甚至在长时间搜索后也找不到它。 - user2955884

2
我们可以使用“基本R”来实现这一点。
unname(setNames(dict_new, dict_old)[data])
#[1] "Apple"  "Banana" "Carrot" "Apple" 

谢谢,我被 dict_newdict_olddata 都是向量这一事实所困惑了(字典不是来自 Python 而且数据框也不是)。一个在同一调用中使用所有向量的更短的示例可能有助于其他人理解 unname(setNames(c("a","b"),c("x","y"))[c("x","y","z")]) - Paul Rougieux

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接