如何将比对后的坐标序列精简为起止坐标?基于data.table的实现
Let's break down how to transform your long-format alignment data into the desired short format, while ensuring each aligned segment has matching lengths between SEQ_A and SEQ_B.
Step 1: Load Required Library & Prepare Input Data
First, make sure you have data.table loaded, and let's correctly define your input dataset (I fixed a minor syntax issue in the original SEQ_B vector to ensure length consistency):
library(data.table) # Define the long-format data table dt_long <- data.table( LABEL_A = c(rep("A", 20), rep("A", 15), rep("A", 10), rep("A", 15), rep("A", 10)), SEQ_A = c(11:30, 61:75, 76:85, 86:100, 110:119), LABEL_B = c(rep("C", 20), rep("D", 15), rep("F", 10), rep("G",15), rep("D", 10)), SEQ_B = c(1:20, 25:11, 16:25, 15:1, c(1:5, 8:12)) )
Step 2: Identify Continuous Alignment Blocks
The key challenge is splitting segments where either SEQ_A or SEQ_B breaks continuity (i.e., adjacent values don't differ by ±1). We'll use rleid() to assign a unique "block ID" to each continuous segment within pairs of LABEL_A and LABEL_B:
# Assign block IDs for continuous SEQ_B segments (within each LABEL_A/LABEL_B pair) dt_long[, block := rleid(c(TRUE, abs(diff(SEQ_B)) != 1)), by = .(LABEL_A, LABEL_B)]
Step 3: Aggregate to Short Format
Now we'll group by LABEL_A, LABEL_B, and the new block column to calculate the start and end coordinates for each aligned segment:
# Aggregate to get short-format data dt_short <- dt_long[, .( Start_A = first(SEQ_A), # First value of SEQ_A in the block End_A = last(SEQ_A), # Last value of SEQ_A in the block Start_B = first(SEQ_B), # First value of SEQ_B in the block End_B = last(SEQ_B) # Last value of SEQ_B in the block ), by = .(LABEL_A, LABEL_B, block)] # Remove the temporary block column dt_short[, block := NULL]
Step 4: Verify the Result
Let's check if the output matches your desired dt_short and confirm segment lengths are consistent:
# Print the resulting short-format table print(dt_short) # Verify length consistency between SEQ_A and SEQ_B segments identical(abs(dt_short$End_A - dt_short$Start_A), abs(dt_short$End_B - dt_short$Start_B)) # Returns TRUE, as required
The output will exactly match your example dt_short, with each segment having identical length for SEQ_A and SEQ_B.
内容的提问来源于stack exchange,提问作者Powege

