首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R:在特定字符位置拆分蛋白质组数据的dataframe列

R:在特定字符位置拆分蛋白质组数据的dataframe列
EN

Stack Overflow用户
提问于 2020-01-15 00:51:57
回答 2查看 55关注 0票数 2

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

代码语言:javascript
复制
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)

输出仅填充了protein和OS列,但其他列填充了N/A。错误消息如下:

代码语言:javascript
复制
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, ...].

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

EN

回答 2

Stack Overflow用户

发布于 2020-01-15 01:06:08

您的示例仅包含一个字符串。因此,我不确定以下方法是否适用于您的数据。但这是我的尝试。

代码语言:javascript
复制
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中的前两个大写字母和=。最后,我将数据转换为宽格式数据。我希望这对你来说足够了。

代码语言:javascript
复制
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   

这是我尝试过的。

代码语言:javascript
复制
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   
票数 1
EN

Stack Overflow用户

发布于 2020-01-15 01:05:40

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

代码语言:javascript
复制
\s+[^= ]+=

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

代码语言:javascript
复制
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

数据:

代码语言:javascript
复制
x <- "Vimentin OS=Homo sapiens GN=VIM PE=1 SV=4"
df <- data.frame(Description=c(x,x), stringsAsFactors=FALSE)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59738368

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档