13

suffixesinmerge仅适用于常见的列名。无论如何,在合并之前无需手动更新列的情况下,是否也可以将其扩展到其他列?

那是 -

df1 <- data.table(
a = c(1,2,3,4,5,6),
b = c('a','b','f','e','r','h'),
d = c('q','l','o','n','q','z')
)

df2 <- data.table(
a = c(1,2,3,4,5,6),
d = c('q','l','o','n','q','z')
)

colnames(merge(df1,df2, by = 'a', suffixes = c("1","2")))
#[1] "a"  "b"  "d1" "d2" what it does
#[1] "a"  "b1" "d1" "d2" what I'd like it to do

我目前处理这个问题的方式类似于@mrip 的回答。

df1 <- data.table(
a = c(1,2,3,4,5,6),
b = c('a','b','f','e','r','h'),
r = c('a','b','f','e','r','h'),
d = c('q','l','o','n','q','z')
)

df2 <- data.table(
a = c(1,2,3,4,5,6),
c = c('a','b','f','e','r','h'),
q = c('a','b','f','e','r','h'),
d = c('q','l','o','n','q','z')
)

dfmerge <- (merge(df1,df2, by = c("a"), suffixes = c("1","2")))

setnames(
dfmerge,
setdiff(names(df1),names(df2)),
paste0(setdiff(names(df1),names(df2)),"1")
)

setnames(
dfmerge,
setdiff(names(df2),names(df1)),
paste0(setdiff(names(df2),names(df1)),"2")
)

colnames(dfmerge)
#[1] "a"  "b1" "r1" "d1" "c2" "q2" "d2"
4

3 回答 3

12

A simple solution:

mrg<-(merge(df1,df2, by = 'a', suffixes = c("1","2")))
setnames(mrg,paste0(names(mrg),ifelse(names(mrg) %in% setdiff(names(df1),names(df2)),"1","")))
setnames(mrg,paste0(names(mrg),ifelse(names(mrg) %in% setdiff(names(df2),names(df1)),"2","")))

> names(mrg)
[1] "a"  "b1" "d1" "d2"

Edit: thanks to comments by Ricardo Saporta for cleaning this up considerably and teaching me a few new tips!

于 2013-10-02T17:34:54.393 回答
6

尝试以下操作:

colnames(
  mergeWithSuffix(df1,df2, by = 'a', suffixes = c("1","2"))
)
[1] "a"   "b.1" "d.1" "d.2"

请注意,原件data.frames没有受到伤害。

colnames(df1)
[1] "a" "b" "d"

colnames(df2)
[1] "a" "d"

功能如下

require(data.table)

mergeWithSuffix <- function(x, y, by, suffixes=NULL, ...) {

  # Add Suffixes
  mkSuffix(x, suffixes[[1]], merge.col=by)
  mkSuffix(y, suffixes[[2]], merge.col=by)

  # Merge
  ret <- merge(x, y, by = by, suffixes = NULL, ...)

  # Remove Suffixes
  undoSuffix(x, suffixes[[1]], merge.col=by)
  undoSuffix(y, suffixes[[2]], merge.col=by)
  return(ret)
}

mkSuffix <- function(x, sfx, sep=".", merge.col=NULL)  {
  nms <- setdiff(names(x), merge.col)
  setnames(x, nms, paste(nms, sfx, sep=".") ) 
}

undoSuffix <- function(x, sfx, sep=".", merge.col=NULL) {
  nms <- setdiff(names(x), merge.col)
  setnames(x, nms, sub(paste0(get("sep"), sfx, "$"), "", nms))
}

请注意,它setnames通过引用起作用,因此开销几乎可以忽略不计。此外,正如其他地方所讨论的,这同样适用于 data.frames 和 data.table

于 2013-10-02T17:32:07.790 回答
1

这是一个有趣的问题,我怀疑扩展merge将是一个简单的解决方案,除非 Matt Dowle 和 Co. 认为它值得在merge.data.table.

这是想到的一种方法:

DTs <- c("df1", "df2")
suffixes <- seq_along(DTs)

for (i in seq_along(DTs)) {
  Name <- setdiff(colnames(get(DTs[i])), "a")
  setnames(get(DTs[i]), Name, paste(Name, suffixes[i], sep = "."))
}

merge(df1, df2, by = "a") # Will obviously work as you expect now
于 2013-10-02T17:29:18.350 回答