【问题标题】:Find matching pattern between columns and count for each distinct element in one column查找列之间的匹配模式并计算一列中每个不同元素的数量
【发布时间】:2018-12-09 19:26:24
【问题描述】:

我有一个包含大约 7000 万行的制表符分隔文件,如下所示;

chr1:25851453-25869713W:6655:4522:4234:2258:2508:S      6655
chr1:25851453-25869713W:6655:4523:4234:2258:2508:A      6655
chr1:25851453-25869713W:0000:4524:4234:2258:2508:S      6655
chr1:25851453-25869713W:6655:4525:4234:2258:2508:S      6655
chr1:26235471-26237662W:6663:124:1864:311:455:S         6663
chr1:26235471-26237662W:6663:125:1864:311:455:S         6663

我正在尝试为第 2 列中的每个不同元素报告,第 1 列中第二个“:”之后的模式与第 2 列中的模式匹配的次数。

上面的例子是这样的;

6655 matches 3
6655 mismatches 1
6663 matches 2
6663 mismatches 0

(具体来说,第 2 列中有 15559 个不同的值)

谢谢!

【问题讨论】:

  • 到目前为止您尝试过什么?你能发布一些你已经完成的代码吗?

标签: r shell awk cut


【解决方案1】:
$ cat tst.awk
BEGIN { FS="[:\t]" }
prev != $NF { if (NR>1) prt(); prev = $NF }
{ cnt[$3 == $NF]++ }
END { prt() }
function prt() {
    printf "%d matches %d\n", prev, cnt[1]
    printf "%d mismatches %d\n", prev, cnt[0]
    delete cnt
}

$ awk -f tst.awk file
6655 matches 3
6655 mismatches 1
6663 matches 2
6663 mismatches 0

由于您的文件很大,上面使用了键值(每行的最后一个数字)组合在一起的事实,以便我们仅在当前键值更改时打印结果,而不是存储所有数据数组中的键值,然后在文件末尾打印。

【讨论】:

  • 谢谢!在按第二列对文件进行排序后,这工作得很好而且非常快。
【解决方案2】:

我们可以为此使用strsplit

lapply(setNames(unique(df[, 2]), unique(df[, 2])), function(x)
    sum(x == sapply(strsplit(as.character(df[, 1]), ":"), function(y) y[3])))
#$`6655`
#[1] 3
#
#$`6663`
#[1] 2

解释:我们首先从第 2 列中确定唯一条目;然后对于每个唯一条目,我们通过拆分 ":" 上的第 1 列条目来计算与第二个 ":" 之后的条目匹配的数量。

这会以list 的形式返回匹配数

不匹配数量的反例很简单,我把它留给你。


样本数据

df <- read.table(text =
    "chr1:25851453-25869713W:6655:4522:4234:2258:2508:S 6655
chr1:25851453-25869713W:6655:4523:4234:2258:2508:A 6655
chr1:25851453-25869713W:0000:4524:4234:2258:2508:S 6655
chr1:25851453-25869713W:6655:4525:4234:2258:2508:S 6655
chr1:26235471-26237662W:6663:124:1864:311:455:S 6663
chr1:26235471-26237662W:6663:125:1864:311:455:S 6663", header = F)

【讨论】:

  • 感谢您的回答和解释。这很好用,但我的问题主要是文件很大,大约需要 20 小时。但显然适用于较小的数据集。
  • 不用担心@zkaragoz;我没有意识到您正在寻找awk/non-R 解决方案。
【解决方案3】:

可以先使用gsub 提取column1 中的第二个: 之后的FirstElement。那么使用dplyr的解决方案可以是在column2上分组(例如V2),然后将V2FirstElement匹配和不匹配计算为:

library(dplyr)

df %>% 
   mutate(FirstElement = gsub("^chr1:[^:]*:(\\d+):.*","\\1",V1)) %>%
  group_by(V2) %>%
  summarise(matches = sum(V2==FirstElement), mismatches = sum(V2!=FirstElement))

# # A tibble: 2 x 3
#      V2 matches mismatches
#   <int>   <int>      <int>
# 1  6655       3          1
# 2  6663       2          0

数据:

df <- read.table(text="
chr1:25851453-25869713W:6655:4522:4234:2258:2508:S 6655
chr1:25851453-25869713W:6655:4523:4234:2258:2508:A 6655
chr1:25851453-25869713W:0000:4524:4234:2258:2508:S 6655
chr1:25851453-25869713W:6655:4525:4234:2258:2508:S 6655
chr1:26235471-26237662W:6663:124:1864:311:455:S 6663
chr1:26235471-26237662W:6663:125:1864:311:455:S 6663",
stringsAsFactors = FALSE)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-04
    • 2016-05-25
    • 2015-08-10
    • 1970-01-01
    相关资源
    最近更新 更多