如何找到适合特定范围(每个人)的列并添加 1,否则 0,使用 R

How to find columns that fit an specific range (per individual) and add 1, else 0, using R

我有一个包含三个初始列的数据框:ID、开始和结束 positions.The 其余列是数字染色体位置,它看起来像这样:

ID   start  end  1  2  3  4  5  6  7  ...  n
ind1  2      4   
ind2  1      3
ind3  5      7

我想要的是根据每个人的范围 (start:end) 填写空列 (1:n)。例如,在第一个个体 (ind1) 中,范围从位置 2 到 4,然后那些符合范围的位置用一 (1) 填充,而那些超出范围的位置用零 (0) 填充。为简化起见,所需的输出应如下所示:

ID   start  end  1  2  3  4  5  6  7  ...  n
ind1  2      4   0  1  1  1  0  0  0  ...  0 
ind2  1      3   1  1  1  0  0  0  0  ...  0 
ind3  5      7   0  0  0  0  1  1  1  ...  1

我将不胜感激。

如果您从数据框 df 开始,而没有添加列,

    ID start end
1 ind1     2   4
2 ind2     1   3
3 ind3     5   7

你可以做到

mx <- max(df[-1])
M <- Map(function(x, y) replace(integer(mx), x:y, 1L), df$start, df$end)
cbind(df, do.call(rbind, M))
#     ID start end 1 2 3 4 5 6 7
# 1 ind1     2   4 0 1 1 1 0 0 0
# 2 ind2     1   3 1 1 1 0 0 0 0
# 3 ind3     5   7 0 0 0 0 1 1 1

新列的数量将等于 startend 列的最大值。

数据:

df <- structure(list(ID = structure(1:3, .Label = c("ind1", "ind2", 
"ind3"), class = "factor"), start = c(2L, 1L, 5L), end = c(4L, 
3L, 7L)), .Names = c("ID", "start", "end"), class = "data.frame", row.names = c(NA, 
-3L))

假设您知道可以使用 data.table 包中的 between 函数的列数:

cols <- paste0('c',1:7)

library(data.table)
setDT(DF)[, (cols) := lapply(1:7, function(x) +(between(x, start, end)))][]

给出:

     ID start end c1 c2 c3 c4 c5 c6 c7
1: ind1     2   4  0  1  1  1  0  0  0
2: ind2     1   3  1  1  1  0  0  0  0
3: ind3     5   7  0  0  0  0  1  1  1

备注

  • 最好不要只用数字来命名你的列。因此,我在列名的开头添加了一个 c
  • +(between(x, start, end))中使用+是一种技巧。更惯用的方法是使用 as.integer(between(x, start, end)).

已用数据:

DF <- read.table(text="ID   start  end
ind1  2      4   
ind2  1      3
ind3  5      7", header=TRUE)