在R中:如何在两个独立的数据帧中一致地替换(/anonimize)id或名称



假设我有两个数据帧,df1df2。两个数据帧都具有标识符CCD_ 3。我的目标是合并这个标识符上的那些数据集,但我想匿名id列中的名称。然而,问题是,我想分别对两个数据集这样做,因此对df1df2这样做,而不是直接对df3这样做(因为这很容易:只需用一些随机字符替换id列(

我想我的解决方案应该是这样的。首先,我制作了一个单独的数据帧,由来自df1df2的所有唯一的id组成。然后,我需要分配一些随机化,例如idxxxx,其中xxxx是该单独数据帧中每个id的唯一编号。使用dplyrgsubstringr方法,我可以根据在该单独数据帧中分配的值来替换df1df2中的ids。之后,我将合并这两个数据集。

这里我有两个示例数据帧,我试图解决问题,以及期望的结果。请注意,id的数量对我来说并不重要(例如,John Terry是否有id0004或id0003并不重要,只要它在两个数据帧内都一致更改即可。

有人能帮我吗?谢谢

id <- c("John Williams", "John Terry", "Rick Fire", "Katie Blue", "Unknown")
row1 <- c("28", "17", "17", "29", "39")
df1 <- data.frame(id,row1)
id <- c("Frank Johnson", "John Terry", "Rick Fire", "Katie Blue")
row2 <- c("Purple", "Red", "Yellow", "Green")
df2 <- data.frame(id,row2)
df3 <- merge(df1, df2, all.x = TRUE, all.y = TRUE)
#My try
#Make separate data frame
id_df <- merge(df1, df2, all.x = TRUE, all.y = TRUE)
id_df <- subset(id_df,TRUE,select = c(id))
id_df$anonymous <- id_df %>% mutate(id = row_number()) #it would be nicer to have something like id0001
#Replace ids within df1 and df2 according to the id_df anonymous variable
library(stringr)
df1$id <- str_replace(df1$id, id_df$id, as.character(id_df$anonymous)) #replacement does not work
#desired result
#df1        row1
#id0003     28 
#id0002     17
#id0005     17
#id0004     29
#id0006     39
#df2        row2
#id0001     Purple
#id0002     Red
#id0005     Yellow
#id0004     Green
#df3
#id         #row1       #row2
#id0001     NA          Purple
#id0002     17          Red
#id0003     28          NA
#id0004     29          Green
#id0005     17          Yellow
#id0006     39          NA

如果你想匿名化id并使其反向变得相当困难,你可以计算每个字符串的md5哈希。两个相同的字符串将产生相同的md5散列:

df1$id <- sapply(df1$id, digest::digest, algo = "md5")
df2$id <- sapply(df2$id, digest::digest, algo = "md5")
df3 <- merge(df1, df2, all.x = TRUE, all.y = TRUE)
df3
#>                                 id row1   row2
#> 1 22e35044ed452870ad5b014e87121d9d   39   <NA>
#> 2 69d61b42a2f549c4765699f06de3b351   28   <NA>
#> 3 ad1cc76e26c5d73ba4a03bf51df1b6af   17 Yellow
#> 4 b3bdcc4913da319308e6ddf47e09da12 <NA> Purple
#> 5 badea53ae1e8a2fa66ebd1cdde9dd413   17    Red
#> 6 d1f305c19a2f9649abe11efcf26ac645   29  Green

这里有一个所有基为R(没有tidyverse(的解决方案。我们创建了一个具有所有唯一ID的查找表(使用设置操作union来查找ID(,然后分别使用每个数据帧创建查找表merge

# Find all unique ids and create a lookup table.
all_ids <- union(df1$id, df2$id)
id_df <- data.frame(id = all_ids, code = paste0('id', sprintf('%04d', 1:length(all_ids))))
# Merge df1 with the lookup table, remove the id column, and rename the code column to id.
df1 <- merge(df1, id_df, all.x = TRUE)
df1 <- df1[, c('code', 'row1')]
names(df1)[1] <- 'id'
# Repeat for df2
df2 <- merge(df2, id_df, all.x = TRUE)
df2 <- df2[, c('code', 'row2')]
names(df2)[1] <- 'id'
df3 <- merge(df1, df2, all.x = TRUE, all.y = TRUE)

注意sprintf('%04d,…(`将用零填充数字代码,总长度为4。

一个小型解决方案,满足您在加入之前不在df3上操作的请求

id_df <- data.frame(id = union(df1$id,df2$id))
id_df <- 
id_df %>% 
mutate(anonymous = paste0("id", stringr::str_pad(row_number(), 
width = 4, 
pad = 0)))
newdf1 <- left_join(df1, id_df) %>% select(-id) %>% relocate(anonymous)
newdf2 <- left_join(df2, id_df) %>% select(-id) %>% relocate(anonymous)
full_join(newdf1, newdf2)
#> Joining, by = "anonymous"
#>   anonymous row1   row2
#> 1    id0001   28   <NA>
#> 2    id0002   17    Red
#> 3    id0003   17 Yellow
#> 4    id0004   29  Green
#> 5    id0005   39   <NA>
#> 6    id0006 <NA> Purple

最新更新