我想将R中数据框的一列拆分为多列。蛋白质组学数据的表$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)
输出仅填充了protein和OS列,但其他列填充了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, ...].有人知道如何调整代码吗?
发布于 2020-01-15 01:06:08
您的示例仅包含一个字符串。因此,我不确定以下方法是否适用于您的数据。但这是我的尝试。
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 发布于 2020-01-15 01:05:40
这不是最好看的代码,但对于基本的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)https://stackoverflow.com/questions/59738368
复制相似问题