根据另一个数据框中的转换表替换列中的字符

时间:2015-07-21 03:46:45

标签: r replace

我有data.frame mapping,其中包含路径和地图。 我还有另一个data.frame DATA,其中包含原始路径和值。 编辑:路径可能包含两个或更多组件:例如“A> C”或“A> C> B”

set.seed(24);
DATA <- data.frame(
            path=paste0(sample(LETTERS[1:3], 25, replace=TRUE), ">", sample(LETTERS[1:3], 25, replace=TRUE)),
            value=rnorm(25)
        )
mapping <- data.frame(path=c("A","B","C"), map=c("X","Y","Z"))

lapply(mapping, function (x) {
  for (i in 1:nrow(DATA)) {
    DATA$path[i] <- gsub(as.character(x["path"]),as.character(x["map"]),as.character(DATA$path[i]))    
  }
})

我正在尝试将DATA中的路径替换为mapping中的地图值,但这对我来说似乎不起作用。

“A&gt; C”将转换为“X&gt; Z”。

我知道for R中的for循环并不好,但我想不出另一种编码方式。我正在使用的数据大小为DATA中的6米行和mapping中的16k行。

对数据的澄清:虽然路径现在由字母(ABC)组成,但实际路径实际上是域名。路径中的步数也不固定为2,可以是任意数字。

3 个答案:

答案 0 :(得分:5)

您可以使用chartr

  DATA$path <- chartr('ABC', 'XYZ', DATA$path)

或者,如果我们使用来自&#39;映射&#39;

的数据
  DATA$path <- chartr(paste(mapping$path, collapse=''), 
                    paste(mapping$map, collapse=''), DATA$path)

或使用gsubfn

  library(gsubfn)
  pat <- paste0('[', paste(mapping$path, collapse=''),']')
  indx <- setNames(as.character(mapping$map), mapping$path)
  gsubfn(pat, as.list(indx), as.character(DATA$path))

或基于@ smci评论

base R选项
  vapply(strsplit(as.character(DATA$path), '>'), function(x) 
                 paste(indx[x], collapse=">"), character(1L))

答案 1 :(得分:2)

使用data.table1.9.5+),特别建议您提供数据大小的b / c。

library(data.table)
setDT(DATA); setDT(mapping)
DATA[,paste0("path",1:2):=tstrsplit(path,split=">")]
setkey(DATA,path1)[mapping,new.path1:=i.map]
setkey(DATA,path2)[mapping,new.path2:=i.map]
DATA[,new.path:=paste0(new.path1,">",new.path2)]

如果你想摆脱额外的列:

DATA[,paste0(c("","","new.","new."),"path",rep(1:2,2)):=NULL]

如果您只想覆盖path,请在最后一行的LHS上使用path,而不是new.path

这也可以写得更简洁:

library(data.table)
setDT(mapping)
setkey(setkey(setDT(DATA)[,paste0("path",1:2):=tstrsplit(path,split=">")
                          ],path1)[mapping,new.path1:=i.map],path2
       )[mapping,new.path:=paste0(new.path1,">",i.map)]

答案 2 :(得分:0)

我认为您使用了错误的申请。

mapply允许你使用函数的两个参数,这里是路径和地图。请注意,在mapply中,参数FUN首先出现。您也不需要逐行执行此操作,您可以立即执行整个列。最后,在应用中,变量不像在for循环中那样更新,因此您需要在.GlobalEnv中分配它们。您可以通过显式调用assign()或使用&lt;&lt; - 将它们放在堆栈中找到它们的第一个位置来完成此操作。在这种情况下,这将返回.GlobalEnv。

如上所述定义映射和DATA之后,请尝试此操作。

#ifdef A_STATE
#import "a.h"
#else
#import "b.h"
#endif

请注意,对隐形的调用会抑制mapply的输出。

如果你真的想使用lapply,你可以。但是你需要转置映射。你可以这样做,但它会被转换为矩阵,所以你必须将其转换回来。然后,您可以使用&lt;&lt; - 并且不使用上面的for循环来获取此代码:

head(DATA)
invisible(mapply( function (x,y) {
  DATA$path <<- gsub(x,y,DATA$path)    
},mapping$path, mapping$map))

head(DATA)

感谢分享,我学到了很多回答这个问题。

相关问题