计算以逗号分隔的值并在 R 中复制一个值相等的次数
Count comma delimited values and replicate a value equal times in R
给定以下示例数据...
id Proteins
522 Q9UHC7-4;Q9UHC7-3;Q9UHC7-2;Q9UHC7
523 Q9UHV7
524 Q9Y6T7-2;Q9Y6T7
525 Q9Y6T7-2;Q9Y6T7
...我想创建第三列,每列 id
乘以每行的分号分隔值的数量。更具体地说是这样的:
id Proteins newCol
522 Q9UHC7-4;Q9UHC7-3;Q9UHC7-2;Q9UHC7 522;522;522;522
523 Q9UHV7 523
524 Q9Y6T7-2;Q9Y6T7 524;524
525 Q9Y6T7-2;Q9Y6T7 525;525
我试过这个 dt$newCol <- rep(dt$id, lengths(str_split(dt$Proteins, ";")))
但不起作用,因为它会创建一个更长的列表。
library(tidyverse)
df %>%
mutate(newCol = map2_chr(id, str_count(Proteins, ";") + 1, ~str_c(rep(.x, .y), collapse = ";")))
是这样的吗?
library(stringr)
df$newCol <- str_replace_all(df$Proteins, "[^;]+", as.character(df$id))
输出
> df
id Proteins newCol
1 522 Q9UHC7-4;Q9UHC7-3;Q9UHC7-2;Q9UHC7 522;522;522;522
2 523 Q9UHV7 523
3 524 Q9Y6T7-2;Q9Y6T7 524;524
4 525 Q9Y6T7-2;Q9Y6T7 525;525
@markus
建议的另一个 Base R 解决方案
df1$new <- Map(gsub, pattern = "[^;]+", replacement = df1$id, x = df1$Proteins)
基本的 R 解决方案是计算 ";"
出现的次数,向其添加 +1,相应地重复 id
。使用 tapply
将 id 粘贴在一起以创建 newCol
.
x <- rep(df$id, lengths(regmatches(df$Proteins, gregexpr(";", df$Proteins))) + 1)
df$newCol <- tapply(x, x, paste0, collapse = ';')
df
# id Proteins newCol
#1 522 Q9UHC7-4;Q9UHC7-3;Q9UHC7-2;Q9UHC7 522;522;522;522
#2 523 Q9UHV7 523
#3 524 Q9Y6T7-2;Q9Y6T7 524;524
#4 525 Q9Y6T7-2;Q9Y6T7 525;525
我们可以使用 for
循环 gsub
for(i in seq_len(nrow(df1))) df1$newCol[i] <- gsub("([[:alnum:]-]+)", df1$id[i], df1$Proteins[i])
df1
# id Proteins newCol
#1 522 Q9UHC7-4;Q9UHC7-3;Q9UHC7-2;Q9UHC7 522;522;522;522
#2 523 Q9UHV7 523
#3 524 Q9Y6T7-2;Q9Y6T7 524;524
#4 525 Q9Y6T7-2;Q9Y6T7 525;525
给定以下示例数据...
id Proteins
522 Q9UHC7-4;Q9UHC7-3;Q9UHC7-2;Q9UHC7
523 Q9UHV7
524 Q9Y6T7-2;Q9Y6T7
525 Q9Y6T7-2;Q9Y6T7
...我想创建第三列,每列 id
乘以每行的分号分隔值的数量。更具体地说是这样的:
id Proteins newCol
522 Q9UHC7-4;Q9UHC7-3;Q9UHC7-2;Q9UHC7 522;522;522;522
523 Q9UHV7 523
524 Q9Y6T7-2;Q9Y6T7 524;524
525 Q9Y6T7-2;Q9Y6T7 525;525
我试过这个 dt$newCol <- rep(dt$id, lengths(str_split(dt$Proteins, ";")))
但不起作用,因为它会创建一个更长的列表。
library(tidyverse)
df %>%
mutate(newCol = map2_chr(id, str_count(Proteins, ";") + 1, ~str_c(rep(.x, .y), collapse = ";")))
是这样的吗?
library(stringr)
df$newCol <- str_replace_all(df$Proteins, "[^;]+", as.character(df$id))
输出
> df
id Proteins newCol
1 522 Q9UHC7-4;Q9UHC7-3;Q9UHC7-2;Q9UHC7 522;522;522;522
2 523 Q9UHV7 523
3 524 Q9Y6T7-2;Q9Y6T7 524;524
4 525 Q9Y6T7-2;Q9Y6T7 525;525
@markus
建议的另一个 Base R 解决方案df1$new <- Map(gsub, pattern = "[^;]+", replacement = df1$id, x = df1$Proteins)
基本的 R 解决方案是计算 ";"
出现的次数,向其添加 +1,相应地重复 id
。使用 tapply
将 id 粘贴在一起以创建 newCol
.
x <- rep(df$id, lengths(regmatches(df$Proteins, gregexpr(";", df$Proteins))) + 1)
df$newCol <- tapply(x, x, paste0, collapse = ';')
df
# id Proteins newCol
#1 522 Q9UHC7-4;Q9UHC7-3;Q9UHC7-2;Q9UHC7 522;522;522;522
#2 523 Q9UHV7 523
#3 524 Q9Y6T7-2;Q9Y6T7 524;524
#4 525 Q9Y6T7-2;Q9Y6T7 525;525
我们可以使用 for
循环 gsub
for(i in seq_len(nrow(df1))) df1$newCol[i] <- gsub("([[:alnum:]-]+)", df1$id[i], df1$Proteins[i])
df1
# id Proteins newCol
#1 522 Q9UHC7-4;Q9UHC7-3;Q9UHC7-2;Q9UHC7 522;522;522;522
#2 523 Q9UHV7 523
#3 524 Q9Y6T7-2;Q9Y6T7 524;524
#4 525 Q9Y6T7-2;Q9Y6T7 525;525