【问题标题】:merge data frames based on non-identical values in R基于R中的不同值合并数据帧
【发布时间】:2012-12-04 00:34:05
【问题描述】:

我有两个数据框。第一个看起来像

dat <- data.frame(matrix(nrow=2,ncol=3))
names(dat) <- c("Locus", "Pos", "NVAR")
dat[1,] <- c("ACTC1-001_1",   "chr15:35087734..35087734", "1" )
dat[2,] <- c("ACTC1-001_2 ",  "chr15:35086890..35086919", "2")

其中 chr15:35086890..35086919 表示此范围内的所有数字。

第二个看起来像:

dat2 <- data.frame(matrix(nrow=2,ncol=3))
names(dat2) <- c("VAR","REF.ALT","     FUNC")
dat2[1,] <- c("chr1:116242719",   "T/A", "intergenic" )
dat2[2,] <- c("chr1:116242855",  "A/G", "intergenic")

我想通过 dat$Pos 和 dat2$VAR 中的值合并这些。如果 dat2$VAR 中的单元格中的单个数字包含在 dat$Pos 中的单元格范围内,我想合并这些行。如果这种情况发生不止一次(dat2$VAR 在 dat$Pos 中的多个范围内,我希望它每次都合并)。最简单的方法是什么?

【问题讨论】:

  • 我会使用一些正则表达式并添加新列。 dat2$VAR_fix &lt;- as.integer(gsub('chr1:', '', dat2$VAR))。而且我会将 dat$Pos 分成两列的下限和上限。然后您可以使用实际数字进行检查。
  • dat2 中的数字是否可以出现在dat 的多行中?
  • 是否可以取消汇总dat,即转换它,使其每行有一个数字而不是范围(我们可以为其提供算法),还是会导致太多可能性?
  • 还知道你的两个 data.frame 有多大会有所帮助。
  • 我可以像贾斯汀那样分裂,但我想看看是否有更简单的方法。是的,dat2 数字可能会重复,我确实提到过。我可以取消总结 dat,但它会失去一些意义。并且,dat 为 865*12,dat2 为 5553*10。

标签: r merge


【解决方案1】:

这是一个解决方案,很短但不是特别有效,因此我不建议将它用于大数据。但是,您似乎表明您的数据不是那么大,所以请尝试一下并告诉我:

library(plyr)

exploded.dat <- adply(dat, 1, function(x){
    parts <- strsplit(x$Pos, ":")[[1]]
    chr   <- parts[1]
    range <- strsplit(parts[2], "..", fixed = TRUE)[[1]]
    start <- range[1]
    end   <- range[2]
    data.frame(VAR = paste(chr, seq(from = start, to = end), sep = ":"), x)
})

merge(dat2, exploded.dat, by = "VAR")

如果它太慢或使用太多内存来满足您的需求,您将不得不实现一些更复杂的东西,而另一个问题看起来是一个很好的起点:Merge by Range in R - Applying Loops

【讨论】:

  • 我认为你可能不得不逃避这些点。
  • @RicardoSaporta,不,因为我使用 strsplitfixed = TRUE
  • flodel,我是否正确地说 strsplit 适用于矩阵,但不适用于数据帧?因为当我在 dat (一个数据框)上尝试这个时,我在 strsplit(x$POS, ":") 中得到错误:非字符参数。当我转换为矩阵并将这一行编辑为部分
  • 不,这一定是因为class(dat$POS)factor 或其他东西,而不是character,如您的示例。尝试将其类更改为character 或在我的代码中将x$Pos 替换为as.character(x$Pos)
  • 我还设法通过使用 Bioconductor 的 IRanges 包解决了这个问题,我不好意思地承认它就是为这个问题而设计的。虽然学习不同的方法来解决问题总是好的。
【解决方案2】:

请尝试一下,让我们知道它是如何工作的。如果没有更大的数据集,很难解决问题。如果由于某种原因它不起作用,请从您的数据表中再分享几行(特别是匹配的行)

拼接数据

range.strings <- do.call(rbind, strsplit(dat$Pos, ":"))[, 2]
range.strings <- do.call(rbind, strsplit(range.strings, "\\.\\."))

mins <- as.numeric(range.strings[,1])
maxs <- as.numeric(range.strings[,2])

d2.vars <- as.numeric(do.call(rbind, str_split(dat2$VAR, ":"))[,2])
names(d2.vars) <- seq(d2.vars)

查找匹配项

# row numebr is the row in dat
# col number is the row in dat2 
matches <- sapply(d2.vars, function(v)  mins < v & v <= maxs)

合并

# create a column in dat to merge-by
dat <- cbind(dat, VAR=NA)

# use the VAR in dat2 as the merge id
sapply(seq(ncol(matches)), function(i)
    dat$VAR <- dat2[i, "VAR"] )

merge(dat, dat2)

【讨论】:

  • 我希望匹配行中的所有列都放在同一行上。所以 dat2 在匹配的行中添加到 dat1,作为额外的列。
  • 我认为您错过了这一点,x..y 表示法表示整个 [x, y] 范围,因此使用 grep 是不够的。我什至认为在进行合并时需要考虑chr1(染色体编号?)。
  • 我把它理解为一个长字符串......但你的意思是它应该是 x
  • 是的 chr 是染色体,所以要包括数字。 var 可以等于,也可以在 X 和 Y 之内。
  • @pepsi,我还不清楚的部分:dat2 中的一行可以与 dat 中的多行匹配吗?
猜你喜欢
  • 2020-10-10
  • 2018-03-18
  • 2019-12-07
  • 1970-01-01
  • 1970-01-01
  • 2021-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多