【问题标题】:R: split dataframe column of proteomics data at specific character positionsR:在特定字符位置拆分蛋白质组学数据的数据框列
【发布时间】:2020-01-14 16:51:56
【问题描述】:

我想将 R 中数据框的一列拆分为多列。蛋白质组学数据的 table$Description 有许多行,如下所示:

Vimentin OS=Homo sapiens GN=VIM PE=1 SV=4

最好将此表$Description 拆分为 5 个单独的列,分别命名为“protein”、“OS”、“GN”、“PE”和“SV”。

我尝试了以下方法:

separate(table, Description, c("protein","OS","GN","PE","SV"),sep = c(' OS=',' GN=',' PE=',' SV='), convert = TRUE)

输出仅填充蛋白质和操作系统列,但其他填充为 N/A。 错误信息如下:

1: In stringi::stri_split_regex(value, sep, n_max) :
  longer object length is not a multiple of shorter object length
2: Expected 5 pieces. Missing pieces filled with `NA` in 11149 rows [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...].

有人知道如何调整代码吗?

【问题讨论】:

    标签: r string dataframe split


    【解决方案1】:

    您的示例仅包含一个字符串。所以我不确定以下内容是否适用于您的数据。但这是我的尝试。

    mydf <- tibble(id = 1:2,
                   text = c("Vimentin OS=Homo sapiens GN=VIM PE=1 SV=4",
                            "Vimentin OS=Homo sapiens GN=VIM PE=2 SV=8"))
    
    separate(mydf, col = text, into = c("Protein", "OS","GN","PE","SV"),
             sep = "\\s(?=[A-Z])") %>% 
    mutate_at(vars(OS:SV),
            .funs = list(~sub(x = ., pattern = "^[A-Z]{2}=", replacement = "")))
    
    #    id Protein  OS           GN    PE    SV   
    #  <int> <chr>    <chr>        <chr> <chr> <chr>
    #1     1 Vimentin Homo sapiens VIM   1     4    
    #2     2 Vimentin Homo sapiens VIM   2     8  
    

    更新

    既然你说你的真实数据有不同的性质,我创建了伪数据。我希望这与您所拥有的足够相似。在第 2 行和第 3 行中,缺少一些信息,而第 1 行包含您之前描述的所有内容。我用stri_split_regex() 分割文本。然后,对于每个列表,我基本上为列表中的向量创建并分配了名称。然后,我使用stack() 创建了一个数据框。在map_dfr() 之后,我修剪了列中的前两个大写字母和=,values。最后,我将数据转换为宽格式数据。我希望这对你来说已经足够了。

    mydf <- tibble(id = 1:3,
                   text = c("Vimentin OS=Homo sapiens GN=VIM PE=1 SV=4",
                            "Vimentin OS=Homo sapiens GN=VIM PE=2",
                            "Vimentin OS=Homo sapiens PE=1 SV=4"))
    
         id text                                                                         
    1     1 Vimentin OS=Homo sapiens GN=VIM PE=1 SV=4
    2     2 Vimentin OS=Homo sapiens GN=VIM PE=2     
    3     3 Vimentin OS=Homo sapiens PE=1 SV=4   
    

    这是我尝试过的。

    library(tidyverse)
    library(stringi)
    
    stri_split_regex(str = mydf$text, pattern = "\\s(?=[A-Z])") %>% 
    map_dfr(.f = function(x){
                   # Get OS, GN, PE, and SV
                   foo <- stri_extract_all_regex(str = x, pattern = "^[A-Z]{2}") %>%
                          unlist %>% 
                          .[complete.cases(.)]
    
                   # Now create names for the vector
                   mynames <- c("Protein", foo)
    
                   # Assign the names to the vector
                   names(x) <- mynames
    
                   stack(x)},
    
            .id = "id") %>% 
    mutate(values = sub(x = values, pattern = "^[A-Z]{2}=", replacement = "")) %>% 
    pivot_wider(id_cols = id, names_from = ind, values_from = values,
               values_fill = list(values = NA)) 
    
    #  id    Protein  OS           GN    PE    SV   
    #  <chr> <chr>    <chr>        <chr> <chr> <chr>
    #1 1     Vimentin Homo sapiens VIM   1     4    
    #2 2     Vimentin Homo sapiens VIM   2     NA   
    #3 3     Vimentin Homo sapiens NA    1     4   
    

    【讨论】:

    • 感谢您的回答。我现在重写了代码:separate(table, Description, c("protein","OS","GN","PE","SV"),sep = " [A-Z]{2}=") 它是适用于描述中定义了 OS、GN、PE 和 SV 的所有行。现在我意识到有些行不包含例如信息。 GN 和单独的功能在那里无法正常工作
    • @JanineLux 你的数据看起来怎么样?你能提供一些你在问题中所做的例子吗?
    • @JanineLux 我创建了一个伪数据。看看你是否可以从中获取任何东西并开始你的项目。
    • 非常感谢您的帮助!数据看起来像这样,除了没有 id 列,但在您的示例中标记的文本之后还有很多其他列。不知何故,当我尝试这种方法时,出现以下错误:names(x)
    • @JanineLux 很明显,您的刺痛模式与我创建的模式不同。该命名部分正在为矢量元素创建名称。错误消息告诉您向量元素的数量和名称的数量不匹配。如果你能分享数据,我很乐意看看。否则,从这一点上我无能为力。
    【解决方案2】:

    不是最好看的代码,但对于基本 R 选项,我们可以尝试按以下模式拆分字符串:

    \s+[^= ]+=
    

    这将消耗所有键,只留下您想要的五个值。然后,我们可以转换为数据框,转置,最后应用列名。

    df <- data.frame(t(data.frame(sapply(df$Description, function(x) strsplit(x, "\\s+[^= ]+=")))))
    names(df) <- c("protein", "OS", "GN", "PE", "SV")
    df
    
                                                 protein           OS  GN PE SV
    Vimentin.OS.Homo.sapiens.GN.VIM.PE.1.SV.4   Vimentin Homo sapiens VIM  1  4
    Vimentin.OS.Homo.sapiens.GN.VIM.PE.1.SV.4.1 Vimentin Homo sapiens VIM  1  4
    

    数据:

    x <- "Vimentin OS=Homo sapiens GN=VIM PE=1 SV=4"
    df <- data.frame(Description=c(x,x), stringsAsFactors=FALSE)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-26
      • 2013-11-27
      • 1970-01-01
      • 1970-01-01
      • 2021-02-16
      • 1970-01-01
      相关资源
      最近更新 更多