使用 R 中的散列 table/dictionary 将键列替换为值

Replace key column with values using a hash table/dictionary in R

我想合并两个基于多个列的数据框。这里基于 df1 中的 B 列和 df2 中 X-Z 的所有列,但将 X 列的值返回到 V1。 像字典一样,如果 df1$B 中的 a 与 df2$X 中的 a 匹配,则将 a 返回到 df_merged$V1,但是如果 df1$B 中的 c 与 df2$Y 匹配,则从 df2 返回 b $X,是它的同义词等等。只有df2$X可以返回到df_merged$V1

df1

A   B
1   a
2   c
3   f

和 df2

X   Y   Z
a   NA  NA
b   c   NA
d   e   f

merged_df

A   V1
1   a
2   b
3   d

这是我的尝试:

merge(df1, df2, by.x="B", by.y=c("X", "Y", "Z"), all.x=T)

您通常可以使用 tidyverse 来执行此操作,或者您实际上可以使用 hash/dictionary-like 数据结构。在 R 中,没有原生散列 table class,但您可以利用 hashmap 包,它在内部使用 Rcpp 来创建类似散列的对象:

library(tidyverse)
library(hashmap)

dict = df2 %>%
  mutate_if(is.factor, as.character) %>%
  mutate(Value = X) %>%
  gather(Label, Key, -Value) %>%
  na.omit() %>%
  {hashmap(.$Key, .$Value)}

这给你一个散列 table:

> dict
## (character) => (character)
##         [e] => [d]        
##         [d] => [d]        
##         [f] => [d]        
##         [b] => [b]        
##         [a] => [a] 

现在,要使用 df1$B 作为键提取值,只需执行以下操作:

dict[[df1$B]]
# [1] "a" NA  "a" "d"

df1 %>%
  mutate(Value = dict[[B]]) %>%
  na.omit() %>%
  select(-B)

结果:

  A Value
1 1     a
3 3     a
4 4     d

数据:

df1 = read.table(text = "A   B
                 1   a
                 2   c
                 3   a
                 4   e", header = TRUE, stringsAsFactors = TRUE)

df2 = read.table(text = "X   Y   Z
                 a   NA  NA
                 b   NA  NA
                 d   e   f", header = TRUE, stringsAsFactors = TRUE)

这是用于演示目的的通用版本,但此方法不如使用 hashmap:

健壮、灵活且效率低
library(tidyverse)

df2 %>%
  mutate(Value = X) %>%
  gather(Label, Key, -Value) %>%
  split(.$Label) %>%
  map_dfr(~ cbind(A = na.omit(match(.$Key, df1$B)), 
              slice(., match(df1$B, .$Key)))) %>%
  select(A, Value) %>%
  arrange(A)

结果:

  A Value
1 1     a
2 3     d
3 4     d

数据:

df1 = read.table(text = "A   B
                 1   a
                 2   c
                 3   f
                 4   e", header = TRUE, stringsAsFactors = FALSE)

df2 = read.table(text = "X   Y   Z
                 a   NA  NA
                 b   NA  NA
                 d   e   f", header = TRUE, stringsAsFactors = FALSE)

注:

我首先复制了 df2$X 因为它在技术上也是一把钥匙。然后,我将 df2 重塑为长格式,并将 split 重塑为 Key。对于每个键,我 sliceddf2$B 匹配的行,并将结果与​​ map_dfr 一起 rbind。最后,只返回 Value 列。

请注意,我在此示例中使用了与 hashmap 示例中不同的 df1,因为如果 df1$B 有重复项,此方法将不起作用。