![](/img/trans.png)
[英]Check to see if value from one column is present in two other columns in one dataframe R
[英]Check if column value from one dataframe is in between (range) of two other columns of second dataframe
我有兩個不同大小的數據框:
df1<-data.frame(Chr = c(1, 1,2,3,4),
Start = c(15,120, 210,210,450),
End = c(15,130, 210,210,450),
Gene=c("gene1","gene2","gene3","gene3","gene3"),
sample_id=c("ss6","ss7","ss9","ss9","ss10"))
df2 <- data.frame(Chr = c(1, 1,3),
Start = c(10,100, 200),
End = c(50,200, 250),
Gene=c("gene1","gene2","gene3"),
sample_id=c("ss1","ss1","ss1"))
我想從 df1 獲取 Start 並檢查它是否在 df2 的 Start-End 范圍內,同時確保 Chr 相同(sample_id 不必匹配)。 如果是,則最好使用 df2$sample_id 向 df1 添加一列,但如果不可能,則為 YES(或 NA 表示不匹配)。 它類似於這個問題,但我還需要匹配 'Chr' Only checking range
它也類似於這個問題,我知道它應該更容易,因為我不想匹配相應的行Check if column value is in between (range) of two other column values
我努力了:
df1 %>%
mutate(no_coverage_in = case_when(df2$Start <= Start & df2$End >=Start & Chr == df2$Chr ~ df2$sample_id ))
但它抱怨
較長的 object 長度不是較短的 object 長度的倍數
這是你想要的嗎?
Given data frames
> df1
Chr Start End Gene sample_id
1 1 15 15 gene1 ss6
2 1 120 130 gene2 ss7
3 2 210 210 gene3 ss9
4 3 210 210 gene3 ss9
5 4 450 450 gene3 ss10
> df2
Chr Start End Gene sample_id
1 1 10 50 gene1 ss1
2 1 100 200 gene2 ss1
3 3 200 250 gene3 ss1
vec2 <- c()
for (k in 1:nrow(df1)) {
if (df1$Chr[k] %in% df2$Chr) {
vec <- which(df2$Chr==df1$Chr[k])
for (m in 1:length(vec)) {
if (df1$Start[k]<df2$Start[m] &df1$End[k]<df2$End[m]) {
vec2[k] <- "Yes"
}else{
vec2[k] <- "No"
}
}
}else{
vec2[k] <- "No"
}
}
df1$Results <- vec2
output
> df1
Chr Start End Gene sample_id Results
1 1 15 15 gene1 ss6 Yes
2 1 120 130 gene2 ss7 No
3 2 210 210 gene3 ss9 No
4 3 210 210 gene3 ss9 No
5 4 450 450 gene3 ss10 No
我相信這會給你你想要的結果:
df1 %>%
left_join(df2 %>% rename_at(vars(Start, End, sample_id), paste0, "_2")) %>%
mutate(sample_id_new = case_when(Start < End_2 & Start > Start_2 ~ sample_id_2)) %>%
select(Chr, Start, End, Gene, sample_id, sample_id_new)
Output:
Chr Start End Gene sample_id sample_id_new
1 1 15 15 gene1 ss6 ss1
2 1 120 130 gene2 ss7 ss1
3 2 210 210 gene3 ss9 <NA>
4 3 210 210 gene3 ss9 ss1
5 4 450 450 gene3 ss10 <NA>
您可以編寫一個小的FUN
函數來檢查df1
的每一行,並將其放入循環遍歷其行的lapply
中。
FUN <- \(x, y) {
rng <- df1[x, 2] >= y[, 2] & df1[x, 3] < y[, 3]
chr <- df1[x, 1] == y[, 1]
if (any(rng & chr)) df2[which(rng), 5] else NA
}
df1 <- transform(df1, match=unlist(lapply(seq.int(nrow(df1)), FUN, df2)))
df1
# Chr Start End Gene sample_id match
# 1 1 15 15 gene1 ss6 ss1
# 2 1 120 130 gene2 ss7 ss1
# 3 2 210 210 gene3 ss9 <NA>
# 4 3 210 210 gene3 ss9 ss1
# 5 4 450 450 gene3 ss10 <NA>
我使用新的速記符號在 R>4.1.* 中創建函數。 對於較舊的 R 版本,請使用FUN <- function(x, y)
或更新 R 而不是FUN <- \(x, y)
。
這是一個建議。
df1$match= sapply( 1:nrow(df1) ,
function(x)
any( df1[x, 'Chr']==df2[, 'Chr'] &
df1[x , 'Start'] <= df2[ , 'End'] &
df1[x , 'Start'] >= df2[ , 'Start'] ))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.