R - 循环内循环以提取数据框中多行的多个字符串组合
R - loop within a loop to extract multiple string combinations for multiple rows in data frame
我有一个名为 tabelao
的数据框,它看起来像 dput(head(tabelao)
:
生成的输出
structure(list(sequence = c("prot0", "prot1", "prot2", "prot3", "prot4", "prot5"), start = c(282L, 219L, 641L, 355L, 635L, 526L), end = c(325L, 273L, 682L, 370L, 662L, 560L ), length = c(44L, 55L, 42L, 16L, 28L, 35L), AGI = c(1103L, 962L, 869L, 847L, 799L, 736L), AGR = c(25L, 17L, 20L, 52L, 28L, 21L ), epitope = c("SEFKECFKEVNYDMSYFIRTTNPRETKLVQDIWKKZUTKGDWWQL", "SYAGFEQQRKKFDNPKLKILNVELELKAEKDNPOPRLKDPKQYQSIVDLPOKIIF", "RLEDNPAQWEREKSDEPALLHKELAERRAQQLKJMNRRLANQ", "AYATLOKIQQWKVRKS", "ASCSVKLGLWKNAPOLQWNALELVPDHP", "KKAERCEDPNAWKGPTNGGPOIUQNAGDGAFYGPK" ), comb_per_epitope = c(30, 41, 28, 2, 14, 21)), .Names = c("sequence", "start", "end", "length", "AGI", "AGR", "epitope", "comb_per_epitope" ), row.names = c(NA, 6L), class = "data.frame")
我想做的是以下内容。在 tabelao
的每一行中,我在 tabelao$epitope
上都有一个长度可变的字符串(字符)。从每一行(我的 tabelao
总共有 241 行)我想获得所有可能的 15 个字符的字符串。请注意,我不想要回文序列。为了获得所有这些序列(序列的数量,取决于字符串的长度,由长度 -15 + 1 计算,可以在 tabelao$comb_per_epitope
处看到)我使用了以下循环:
combinations <- c()
for(i in 1:tabelao$comb_per_epitope[1]) { combinations[i] <- str_sub(string = tabelao$epitope[1], start = i, end
= i+14) }
我得到了我想要的结果,即 15 个字符的 30 种可能组合:
> combinations
[1] "SEFKECFKEMNYDMN" "EFKECFKEMNYDMNY" "FKECFKEMNYDMNYF" "KECFKEMNYDMNYFI" "ECFKEMNYDMNYFIR" "CFKEMNYDMNYFIRT" "FKEMNYDMNYFIRTT"
[8] "KEMNYDMNYFIRTTN" "EMNYDMNYFIRTTNP" "MNYDMNYFIRTTNPT" "NYDMNYFIRTTNPTH" "YDMNYFIRTTNPTHE" "DMNYFIRTTNPTHEK" "MNYFIRTTNPTHEKL"
[15] "NYFIRTTNPTHEKLV" "YFIRTTNPTHEKLVQ" "FIRTTNPTHEKLVQD" "IRTTNPTHEKLVQDI" "RTTNPTHEKLVQDIW" "TTNPTHEKLVQDIWK" "TNPTHEKLVQDIWKK"
[22] "NPTHEKLVQDIWKKL" "PTHEKLVQDIWKKLE" "THEKLVQDIWKKLEA" "HEKLVQDIWKKLEAK" "EKLVQDIWKKLEAKG" "KLVQDIWKKLEAKGD" "LVQDIWKKLEAKGDI"
[29] "VQDIWKKLEAKGDIY" "QDIWKKLEAKGDIYL"
但同样,我只能在第一行做到这一点。我现在想在 tabelao
的 241 行中重复此操作。我试图将一个循环放在另一个循环中,但没有成功。除了这个 tabelao
,我还有一个名为 vetores
的 list
,考虑到 tabelao
的每一行,它包含一个数字序列,从 1 开始到数字结束可能的组合,如下所示(我在循环中使用了这个列表,如下所示):
> head(vetores)
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
[[2]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
[[3]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
[[4]]
[1] 1 2
[[5]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14
[[6]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
我的 "double loop" 如下所示:
trial <- c() # I'll store the output of each iterations in this object
for(i in 1:nrow(tabelao)){ # I want 241 iterations, which is the length of tabelao
trial[i] <- for(each in 1:tabelao$comb_per_epitope[i]) {
str_sub(string = tabelao$epitope[each], start = vetores[[each]][each], end = vetores[[each+14]][each+14])
}
}
输出只是 NULL:
> trial
NULL
谁能发现我做错了什么?我知道在一个循环中循环是不可取的。但是,我对 apply
函数族不是很熟悉。
下面的双循环对我有用:
trial <- list()
for(j in 1:nrow(tabelao)){
combinations <- c()
for(i in 1:tabelao$comb_per_epitope[j]) {
combinations[i] <- str_sub(string = tabelao$epitope[j],
start = i,end = i+14)
trial[[j]] <- combinations
}
}
您应该查看 apply、sapply、lapply 等...这样可以更有效地处理这类任务。特别是如果这些 data.frames 很大。考虑将字符串提取循环包装在一个函数中,然后将其应用于您的 data.frame
例如,您也可以使用以下方法实现此目的:
# Wrap the string extraction in a function
string15 <- function(df){
# Define combinations as vector
combinations <- c()
for(i in 1:df$comb_per_epitope) { # Use for loop to loop through combinations
combinations[i] <- str_sub(string = df$epitope, start = i, end
= i+14)
}
# Return the combinations
return(combinations)
}
# Split your dataframe by sequence to get a list of dataframes where each element of the list represents a row of the data.frame
tabelao.splits <- split(tabelao, as.factor(tabelao$sequence))
# Define a list to hold the results and lapply your function
res <- list()
res <- lapply(tabelao.splits, string15)
我会使用 zoo
包中的 rollapply
。在这种情况下,我们将每个字符串拆分为 ''
并在每个字符串中应用 rollapply
函数。 rollapply
将函数 paste
应用于每个字符串的滚动索引。因此,对于每个字符串,它会粘贴 [1:15]、[2:16]、[3:17] 等。
我们最终使用 Map
和 length<-
(作为函数,因此使用反引号)根据您的 comb_per_epitope
变量设置长度。
library(zoo)
Map(`length<-`, lapply(strsplit(tabelao$epitope, ''), function(i)
rollapply(i, 15, by = 1, paste, collapse = '')), tabelao$comb_per_epitope)
我有一个名为 tabelao
的数据框,它看起来像 dput(head(tabelao)
:
structure(list(sequence = c("prot0", "prot1", "prot2", "prot3", "prot4", "prot5"), start = c(282L, 219L, 641L, 355L, 635L, 526L), end = c(325L, 273L, 682L, 370L, 662L, 560L ), length = c(44L, 55L, 42L, 16L, 28L, 35L), AGI = c(1103L, 962L, 869L, 847L, 799L, 736L), AGR = c(25L, 17L, 20L, 52L, 28L, 21L ), epitope = c("SEFKECFKEVNYDMSYFIRTTNPRETKLVQDIWKKZUTKGDWWQL", "SYAGFEQQRKKFDNPKLKILNVELELKAEKDNPOPRLKDPKQYQSIVDLPOKIIF", "RLEDNPAQWEREKSDEPALLHKELAERRAQQLKJMNRRLANQ", "AYATLOKIQQWKVRKS", "ASCSVKLGLWKNAPOLQWNALELVPDHP", "KKAERCEDPNAWKGPTNGGPOIUQNAGDGAFYGPK" ), comb_per_epitope = c(30, 41, 28, 2, 14, 21)), .Names = c("sequence", "start", "end", "length", "AGI", "AGR", "epitope", "comb_per_epitope" ), row.names = c(NA, 6L), class = "data.frame")
我想做的是以下内容。在 tabelao
的每一行中,我在 tabelao$epitope
上都有一个长度可变的字符串(字符)。从每一行(我的 tabelao
总共有 241 行)我想获得所有可能的 15 个字符的字符串。请注意,我不想要回文序列。为了获得所有这些序列(序列的数量,取决于字符串的长度,由长度 -15 + 1 计算,可以在 tabelao$comb_per_epitope
处看到)我使用了以下循环:
combinations <- c()
for(i in 1:tabelao$comb_per_epitope[1]) { combinations[i] <- str_sub(string = tabelao$epitope[1], start = i, end
= i+14) }
我得到了我想要的结果,即 15 个字符的 30 种可能组合:
> combinations
[1] "SEFKECFKEMNYDMN" "EFKECFKEMNYDMNY" "FKECFKEMNYDMNYF" "KECFKEMNYDMNYFI" "ECFKEMNYDMNYFIR" "CFKEMNYDMNYFIRT" "FKEMNYDMNYFIRTT"
[8] "KEMNYDMNYFIRTTN" "EMNYDMNYFIRTTNP" "MNYDMNYFIRTTNPT" "NYDMNYFIRTTNPTH" "YDMNYFIRTTNPTHE" "DMNYFIRTTNPTHEK" "MNYFIRTTNPTHEKL"
[15] "NYFIRTTNPTHEKLV" "YFIRTTNPTHEKLVQ" "FIRTTNPTHEKLVQD" "IRTTNPTHEKLVQDI" "RTTNPTHEKLVQDIW" "TTNPTHEKLVQDIWK" "TNPTHEKLVQDIWKK"
[22] "NPTHEKLVQDIWKKL" "PTHEKLVQDIWKKLE" "THEKLVQDIWKKLEA" "HEKLVQDIWKKLEAK" "EKLVQDIWKKLEAKG" "KLVQDIWKKLEAKGD" "LVQDIWKKLEAKGDI"
[29] "VQDIWKKLEAKGDIY" "QDIWKKLEAKGDIYL"
但同样,我只能在第一行做到这一点。我现在想在 tabelao
的 241 行中重复此操作。我试图将一个循环放在另一个循环中,但没有成功。除了这个 tabelao
,我还有一个名为 vetores
的 list
,考虑到 tabelao
的每一行,它包含一个数字序列,从 1 开始到数字结束可能的组合,如下所示(我在循环中使用了这个列表,如下所示):
> head(vetores)
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
[[2]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
[[3]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
[[4]]
[1] 1 2
[[5]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14
[[6]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
我的 "double loop" 如下所示:
trial <- c() # I'll store the output of each iterations in this object
for(i in 1:nrow(tabelao)){ # I want 241 iterations, which is the length of tabelao
trial[i] <- for(each in 1:tabelao$comb_per_epitope[i]) {
str_sub(string = tabelao$epitope[each], start = vetores[[each]][each], end = vetores[[each+14]][each+14])
}
}
输出只是 NULL:
> trial
NULL
谁能发现我做错了什么?我知道在一个循环中循环是不可取的。但是,我对 apply
函数族不是很熟悉。
下面的双循环对我有用:
trial <- list()
for(j in 1:nrow(tabelao)){
combinations <- c()
for(i in 1:tabelao$comb_per_epitope[j]) {
combinations[i] <- str_sub(string = tabelao$epitope[j],
start = i,end = i+14)
trial[[j]] <- combinations
}
}
您应该查看 apply、sapply、lapply 等...这样可以更有效地处理这类任务。特别是如果这些 data.frames 很大。考虑将字符串提取循环包装在一个函数中,然后将其应用于您的 data.frame
例如,您也可以使用以下方法实现此目的:
# Wrap the string extraction in a function
string15 <- function(df){
# Define combinations as vector
combinations <- c()
for(i in 1:df$comb_per_epitope) { # Use for loop to loop through combinations
combinations[i] <- str_sub(string = df$epitope, start = i, end
= i+14)
}
# Return the combinations
return(combinations)
}
# Split your dataframe by sequence to get a list of dataframes where each element of the list represents a row of the data.frame
tabelao.splits <- split(tabelao, as.factor(tabelao$sequence))
# Define a list to hold the results and lapply your function
res <- list()
res <- lapply(tabelao.splits, string15)
我会使用 zoo
包中的 rollapply
。在这种情况下,我们将每个字符串拆分为 ''
并在每个字符串中应用 rollapply
函数。 rollapply
将函数 paste
应用于每个字符串的滚动索引。因此,对于每个字符串,它会粘贴 [1:15]、[2:16]、[3:17] 等。
我们最终使用 Map
和 length<-
(作为函数,因此使用反引号)根据您的 comb_per_epitope
变量设置长度。
library(zoo)
Map(`length<-`, lapply(strsplit(tabelao$epitope, ''), function(i)
rollapply(i, 15, by = 1, paste, collapse = '')), tabelao$comb_per_epitope)