У меня есть data.frame, который содержит 3 столбца с именем start
, end
и width
. Каждая строка представляет собой сегмент над 1D пространства с началом и концом и ширину такие, как «ширина = конец - старт + 1»Сжать крайние диапазоны в data.frame
Ниже приведен пример
d = data.frame(
start = c(12, 50, 100, 130, 190),
end = c(16, 80, 102, 142, 201)
)
d$width = d$end - d$start + 1
print(d)
start end width
1 12 16 5
2 50 80 31
3 100 102 3
4 130 142 13
5 190 201 12
Рассмотрим две контрольные точки и А фактор разделения
UpperPos = 112
LowerPos = 61
factor = 2
Я хотел бы уменьшить ширину каждого сегмента за пределами двух точек останова таким образом, чтобы уменьшить их ширину с коэффициентом factor
. Если сегмент перекрывает точку останова, то только часть сегмента, которая находится за пределами этой точки останова, должна быть уменьшена по ширине. Кроме того, ширина каждого сегмента должна быть кратной 3 и должна иметь ненулевую длину.
Вот моя текущая функция, что «сжимания» сегменты
squeeze = function(d, factor, LowerPos, UpperPos)
{
for (row in 1:nrow(d))
{
if (d[row,]$end <= LowerPos | d[row,]$end >= UpperPos) # Complete squeeze
{
middlePos = round(d[row,]$start + d[row,]$width/2)
d[row,]$width = round(d[row,]$width/factor)
d[row,]$width = d[row,]$width - d[row,]$width %% 3 + 3
d[row,]$start = round(middlePos - d[row,]$width/2)
d[row,]$end = d[row,]$start + d[row,]$width -1
} else if (d[row,]$start <= LowerPos & d[row,]$end >= LowerPos) # Partial squeeze (Lower)
{
d[row,]$start = round(LowerPos - (LowerPos - d[row,]$start)/factor)
d[row,]$width = d[row,]$end - d[row,]$start + 1
if (d[row,]$width %% 3 != 0)
{
add = 3 - d[row,]$width %% 3
d[row,]$width = d[row,]$width + add
d[row,]$start = d[row,]$start - add
}
} else if (d[row,]$start >= UpperPos & d[row,]$end <= UpperPos) # Partial squeeze (Upper)
{
d[row,]$end = round(UpperPos + (d[row,]$end - UpperPos)/factor)
d[row,]$width = d[row,]$end - d[row,]$start + 1
if (d[row,]$width %% 3 != 0)
{
add = 3 - d[row,]$width %% 3
d[row,]$width = d[row,]$width + add
d[row,]$end = d[row,]$start + add
}
} else if (!(d[row,]$end < UpperPos & d[row,]$start > LowerPos))
{
print(d)
print(paste("row is ",row))
print(paste("LowerPos is ",LowerPos))
print(paste("UpperPos is ",UpperPos))
stop("In MyRanges_squeeze: Should not run this line!")
}
}
return(d)
}
и возвращает ожидаемый результат
squeeze(d)
start end width
1 12 14 3
2 54 80 27
3 100 102 3
4 132 140 9
5 192 200 9
Однако моя функция squeeze
является слишком медленным. Можете ли вы помочь мне улучшить его?
Не ускоряя его, но я думаю, что у вас есть ошибка в вашем первом 'состоянии if'. Не должно быть 'if (d $ end <= LowerPos | d $ start> = UpperPos)'? У вас есть два 'd $ end', но второй должен быть' d $ Start'? – Gregor
Для первой строки '12, 16' сжимается до' 12, 14'. Почему обновляется только «конец»? Почему бы не «13, 15» в результате? Сравните с последней строкой, '190, 201' сжимается до' 192, 200', где оба обновляются. – Gregor