繁体   English   中英

字符串长度与字符串长度列表的按行比较

[英]Rowwise comparison of the length of a string against a list of string lengths

考虑以下包含两列可变长度字符串的数据框:

library("tidyverse")

df <- tibble(REF = c("TTG", "CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT", "T", "TTGTGTGTGTGTGTGTGTGTGT"),
             ALT = c("T", "CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT,CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT", "TTG", "TTGTGTGTGTGTGTGTGTGTGTGT"))

# # A tibble: 4 × 2
# REF                               ALT                                                                
# <chr>                             <chr>                                                              
# 1 TTG                               T                                                                  
# 2 CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT,CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT
# 3 T                                 TTG                                                                
# 4 TTGTGTGTGTGTGTGTGTGTGT            TTGTGTGTGTGTGTGTGTGTGTGT  

与列REF不同,列ALT有时包括几个由逗号连接的字符串(例如第 2 行)。

我想比较REF ( REF_LEN ) 和ALT ( ALT_LEN ) 中字符串的长度,并生成一个带有值的TYPE列:

  • REF_LEN = ALT_LEN时为“SNM”
  • REF_LEN < ALT_LEN时为“INS”
  • REF_LEN > ALT_LEN时为“DEL”

但我想这样做,当ALT中存在多个字符串时,这个新TYPE列的 output 包含这些类型并用逗号分隔。 即,此处预期的 output 为:

"DEL"     "INS,DEL" "INS"     "INS"

到目前为止,我知道如何获取ALT中值的长度,但我无法折叠这些值,因为 output 将包含表中所有ALT的长度,而不仅仅是成对的(即1,35,31,3,24 ):

df %>%
  dplyr::mutate(REF_LEN = str_length(REF),
                ALT_LEN = str_split(ALT, ","),
                ALT_LEN = purrr::map(ALT_LEN, str_length) %>% unlist() %>% paste(collapse = ","))

如您所见,上面的代码是不完整的,但我也无法使用帮助程序 function 来完成上面的TYPE列。 这将返回许多错误,但不确定为什么,因为它似乎可以很好地单独ALT_LEN中的值:

name <- function(alt_lens, ref_len) {
  alt_lens <- unlist(alt_lens)
  ifelse(alt_lens < ref_len, "DEL", ifelse(alt_lens > ref_len, "INS", "SNM"))
}

df %>%
  dplyr::mutate(REF_LEN = str_length(REF),
                ALT_LEN = str_split(ALT, ","),
                TYPE = purrr::map(ALT_LEN, str_length) %>% name(REF_LEN))

有任何想法吗? 谢谢!

这是一个 codegolf-ish 基础 R 解决方案:

df <- data.frame(REF = c("TTG", "CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT", "T", "TTGTGTGTGTGTGTGTGTGTGT"),
             ALT = c("T", "CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT,CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT", "TTG", "TTGTGTGTGTGTGTGTGTGTGTGT"))

df$TYPE <- mapply(
  function(x, y) paste(c("INS", "SNM", "DEL")[2 + sign(nchar(x)- nchar(y))], collapse = ","), 
  df$REF, strsplit(df$ALT, ","), USE.NAMES = FALSE)

df$TYPE
#> [1] "DEL"     "INS,DEL" "INS"     "INS"

reprex package (v2.0.1) 创建于 2022-04-20

更新:删除了第一个答案。 感谢 akrun 指点我。:概念是相同的:将ncharcase_when一起使用,不同之处在于使用tidyr package 中的separate_rows

library(dplyr)
library(tidyr)

df %>% 
  mutate(id = row_number()) %>% 
  separate_rows(ALT, sep = ",") %>% 
  mutate(TYPE = case_when(nchar(REF)==nchar(ALT) ~ "SNM",
                             nchar(REF)< nchar(ALT) ~ "INS",
                             nchar(REF)> nchar(ALT) ~ "DEL",
                             TRUE ~ NA_character_)) %>% 
  group_by(id) %>% 
  mutate(TYPE = toString(TYPE)) %>% 
  slice(1)
 REF                               ALT                                    id TYPE    
  <chr>                             <chr>                               <int> <chr>   
1 TTG                               T                                       1 DEL     
2 CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT CGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGTGT     2 INS, DEL
3 T                                 TTG                                     3 INS     
4 TTGTGTGTGTGTGTGTGTGTGT            TTGTGTGTGTGTGTGTGTGTGTGT                4 INS  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM