我想连接所有具有超过0.955
相似性得分的行。 Abo
和Bel
列分别代表上下行的相似度得分。在以下输入df
中,我有10个基因组探针(NAME
列),它仅在4个基因组区段(dfout
)中连接。
df <- " NAME Abo Bel Chr GD Position
BovineHD0100009217 NA 1.0000000 1 0 31691781
BovineHD0100009218 1.0000000 0.6185430 1 0 31695808
BovineHD0100019600 0.6185430 0.9973510 1 0 69211537
BovineHD0100019601 0.9973510 1.0000000 1 0 69213650
BovineHD0100019602 1.0000000 1.0000000 1 0 69214650
BovineHD0100019603 1.0000000 0.6600000 1 0 69217942
BovineHD0100047112 0.6600000 1.0000000 1 0 93797691
BovineHD0100026604 1.0000000 1.0000000 1 0 93815774
BovineHD0100026605 1.0000000 0.4649007 1 0 93819471
BovineHD0100029861 0.4649007 NA 1 0 105042452"
df <- read.table(text=df, header=T)
我的预期输出dfout
:
dfout <- "Chr start end startp endp nprob
1 31691781 31695808 BovineHD0100009217 BovineHD0100009218 2
1 69211537 69217942 BovineHD0100019600 BovineHD0100019603 4
1 93797691 93819471 BovineHD0100047112 BovineHD0100026605 3
1 105042452 105042452 BovineHD0100029861 BovineHD0100029861 1"
dfout <- read.table(text=dfout, header=T)
有什么想法吗?
答案 0 :(得分:4)
我无法想到使用基本数据框操作的任何漂亮的解决方案,所以这里看起来很糟糕:
首先,将stringsAsFactors
添加到df
创建:
df <- read.table(text=df, header=T, stringsAsFactors = FALSE)
start <- df$Position[1]
end <- integer()
output <- NULL
count <- 1
for (i in 1:(nrow(df)-1)) {
if(df$Bel[i] < 0.955) {
end <- df$Position[i]
output <- rbind(output, c(start, end, df$NAME[which(df$Position == start)], df$NAME[which(df$Position == end)], count))
start <- df$Position[i+1]
count <- 0
}
count <- count + 1
}
end <- df$Position[nrow(df)]
output <- as.data.frame(rbind(output, c(start, end, df$NAME[which(df$Position == start)], df$NAME[which(df$Position == end)], count)))
colnames(output) <- c("start", "end", "startp", "endp", "nprob")
这里的基本思想是循环遍历行并检查是否应将下一行添加到当前段(Bel > 0.955
)或是否应启动新段(Bel <= 0.955
)。当必须启动新序列时,定义endrow,将相应的行添加到输出并且还定义新的起始段。 count
用于添加用于创建细分的行数(nprob
)。
最后,在for循环之外添加最后一个段,输出接收其列名并转换为数据帧。我没有使用Chr
因为1.他们都是平等的,2。如果他们没有给你任何方式来选择/总结它们。
结果:
> output
start end startp endp nprob
1 31691781 31695808 BovineHD0100009217 BovineHD0100009218 2
2 69211537 69217942 BovineHD0100019600 BovineHD0100019603 4
3 93797691 93819471 BovineHD0100047112 BovineHD0100026605 3
4 105042452 105042452 BovineHD0100029861 BovineHD0100029861 1
我非常确定你或其他人可以做到这一点,使其更简洁,更简洁。
答案 1 :(得分:2)
这是dplyr
版本。首先,我们需要定义组,即mutate
位正在执行的操作,然后是组内的简单summarise
函数。
library(dplyr)
df %>%
mutate(
Abo955=ifelse(Abo<0.955,NA,Abo),
myGroup=cumsum(is.na(Abo955)*1)) %>%
group_by(myGroup) %>%
summarise(
Chr=min(Chr),
start=min(Position),
end=max(Position),
startp=first(NAME),
lastp=last(NAME),
nprob=n()) %>%
select(-myGroup)
答案 2 :(得分:1)
此解决方案完全基于逻辑向量,并与提供的示例一起使用。
正如Molx所说,让我们添加stringsAsFactors = F
df <- read.table(text=df, header=T, stringAsFactors = F)
只是为了让逻辑评估工作,让我们将NA改为0
df(is.na(df)) <- 0
现在,对于要连接的连续行,我们可以找到&#34; start&#34;和&#34;结束&#34;使用逻辑评估的行
starts <- df$Bel >= 0.955 & df$Abo < 0.955
ends <- df$Bel < 0.955 & df$Abo >= 0.955
有了这个,我们就可以构建一个data.frame连接需要连接的行
concatenated <- data.frame(Chr = df[starts, "Chr"],
start = df[starts, "Position"],
end = df[ends, "Position"],
startp = df[starts, "NAME"],
endp = df[ends, "NAME"],
nprob = c( diff (which(starts))[1] ,diff (which(ends)))
)
让我们构建一个data.frame,其中包含未连接的行,即那些没有上述行或下行所需的相似性得分的行
notConcatenate <- df$Abo < 0.955 & df$Bel < 0.955
non_concatenated <- data.frame(Chr = df[notConcatenate, "Chr"],
start = df[notConcatenate, "Position"],
end = df[notConcatenate, "Position"],
startp = df[notConcatenate, "NAME"],
endp = df[notConcatenate, "NAME"],
nprob = 1
)
最后绑定两个data.frames
dfout <- rbind(concataneted,non_concatenated)
导致
> dfout
Chr start end startp endp nprob
1 1 31691781 31695808 BovineHD0100009217 BovineHD0100009218 2
2 1 69211537 69217942 BovineHD0100019600 BovineHD0100019603 4
3 1 93797691 93819471 BovineHD0100047112 BovineHD0100026605 3
4 1 105042452 105042452 BovineHD0100029861 BovineHD0100029861 1
注意:此代码假定相关探针位于同一染色体内
干杯!