如何找到适合特定范围(每个人)的列并添加 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
新列的数量将等于 start
和 end
列的最大值。
数据:
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)
我有一个包含三个初始列的数据框: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
新列的数量将等于 start
和 end
列的最大值。
数据:
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)