比较两个数据,在R中逐个单元格地表格

8tntrjer  于 2023-05-26  发布在  其他
关注(0)|答案(2)|浏览(190)

我有两个数据表,dt1dt2,其中前两列代表染色体和位置,其余列代表不同样本的基因型值(0,1,2)。
两个表中的列结构相同(dt 1和dt 2具有相同的样本),但位置可能不同。

dt1 <- data.table(Chromosome = c("chr1", "chr1", "chr2"),
                  Position = c(100, 200, 300),
                  Sample1 = c(0, 0, 1),
                  Sample2 = c(1, 1, 2))

dt2 <- data.table(Chromosome = c("chr1", "chr2", "chr2"),
                  Position = c(200, 300, 400),
                  Sample1 = c(0, 1, 2),
                  Sample2 = c(0, 1, 0))

我想创建第三个表dt3,前两列是染色体和位置。dt 3中的位置列应包括dt 1或dt 2中存在的所有位置。对于每个位置,其余列应代表样品名称,如果两个表之间的基因型不同,或者如果基因型存在于一个表中但不存在于另一个表中,则单元格应标记为1;否则,单元格应标记为0。
这个表很大,所以我期待使用data.table或R的一些特性来进行有效的处理
预期输出:

dt3
   Chromosome Position Sample1 Sample2
1:       chr1      100       1       1 # chr1:100 only exist in dt1
2:       chr1      200       0       1 # chr1:200 is difference in sample2
3:       chr2      300       0       1 # chr2: 300 is difference in sample 2
3:       chr2      400       1       1 # chr2:400 only exist in dt2
6l7fqoea

6l7fqoea1#

您可以使用R中的data.table包有效地实现所需的输出。下面是根据您描述的条件创建dt3表的代码:

library(data.table)

# Convert dt1 and dt2 to data.tables
dt1 <- data.table(dt1)
dt2 <- data.table(dt2)

# Set key columns for efficient merging
setkey(dt1, Chromosome, Position)
setkey(dt2, Chromosome, Position)

# Merge dt1 and dt2 on Chromosome and Position, and create dt3
dt3 <- merge(dt1, dt2, by = c("Chromosome", "Position"), all = TRUE)

# Get the list of sample columns
sample_cols <- colnames(dt3)[!(colnames(dt3) %in% c("Chromosome", "Position"))]

# Loop over sample columns and compute the genotype differences
for (col in sample_cols) {
  dt3[, (col) := ifelse(is.na(get(paste0("Sample1_", col))), 1,
                        ifelse(is.na(get(paste0("Sample2_", col))), 1,
                               ifelse(get(paste0("Sample1_", col)) != get(paste0("Sample2_", col)), 1, 0))), by = .(Chromosome, Position)]
}

# Rename the sample columns to remove the "Sample1_" and "Sample2_" prefixes
setnames(dt3, old = sample_cols, new = gsub("^Sample\\d+_", "", sample_cols))

# Print dt3
print(dt3)

这段代码首先将dt1和dt2转换为data.table对象,并设置键列以实现有效的合并。然后,它对键列执行合并,使用all = TRUE来包括dt1或dt2中存在的所有位置。所得合并表dt3包括来自两个表的所有位置和基因型。
接下来,它在样本列上循环并比较基因型。如果基因型不同,或者基因型存在于一个表中但不存在于另一个表中,则它分配值1。否则,它将赋值为0。
最后,对样本列进行重命名以删除“Sample1_”和“Sample2_”前缀,从而得到所需的输出。
注意:如果您有一个大型数据集,使用data.table和设置键列将有助于优化合并和计算的性能。

kuuvgm7e

kuuvgm7e2#

正如你也标记了这个dplyr一样,有一种方便的方法可以使用dplyr syntax. The dtplyr package will write (and apply) the data.table代码创建data.table`解决方案:

library(data.table)

dt1 <- data.table(Chromosome = c("chr1", "chr1", "chr2"),
                  Position = c(100, 200, 300),
                  Sample1 = c(0, 0, 1),
                  Sample2 = c(1, 1, 2))

dt2 <- data.table(Chromosome = c("chr1", "chr2", "chr2"),
                  Position = c(200, 300, 400),
                  Sample1 = c(0, 1, 2),
                  Sample2 = c(0, 1, 0))

library(dplyr)
library(dtplyr)

dt1 |> 
  lazy_dt() |>
  full_join(dt2, by = c("Chromosome", "Position")) |> 
  mutate(
    Sample1 = as.integer(!mapply(identical, Sample1.x, Sample1.y)),
    Sample2 = as.integer(!mapply(identical, Sample2.x, Sample2.y)),
    .keep = "unused"
  )
#> Source: local data table [4 x 4]
#> Call:   merge(`_DT1`, `_DT2`, all = TRUE, by.x = c("Chromosome", "Position"
#> ), by.y = c("Chromosome", "Position"), allow.cartesian = TRUE)[, 
#>     `:=`(Sample1 = as.integer(!mapply(..identical, Sample1.x, 
#>         Sample1.y)), Sample2 = as.integer(!mapply(..identical, 
#>         Sample2.x, Sample2.y)))][, `:=`(c("Sample1.x", "Sample2.x", 
#> "Sample1.y", "Sample2.y"), NULL)]
#> 
#>   Chromosome Position Sample1 Sample2
#>   <chr>         <dbl>   <int>   <int>
#> 1 chr1            100       1       1
#> 2 chr1            200       0       1
#> 3 chr2            300       0       1
#> 4 chr2            400       1       1
#> 
#> # Use as.data.table()/as.data.frame()/as_tibble() to access results

这为您提供了一些方便的data.table代码,您可以提取、整理和使用这些代码。

dt3 <- merge(
  dt1,
  dt2,
  all = TRUE,
  by = c("Chromosome", "Position")
)

dt3[,
  `:=`(Sample1 = as.integer(!mapply(..identical, Sample1.x, Sample1.y)), 
       Sample2 = as.integer(!mapply(..identical, Sample2.x, Sample2.y)))
  ][, `:=`(c("Sample1.x", "Sample2.x", "Sample1.y", "Sample2.y"), NULL)]

dt3
#>    Chromosome Position Sample1 Sample2
#> 1:       chr1      100       1       1
#> 2:       chr1      200       0       1
#> 3:       chr2      300       0       1
#> 4:       chr2      400       1       1

相关问题